goto、i++、三元运算符、ref和out、String和string、重载运算符_aehyok

原文链接:C#基础知识系列一(goto、i++、三元运算符、ref和out、String和string、重载运算符)

 

前言

这两天在网上看到的总结很多,尤其是博客园中的,很多很多,也给了我很多的启发,当然自己也总结过,而且有很多人也给与我一些意见和看法。不管怎样,自己还是先把所谓的基础知识加强巩固下吧。

2014年的第一篇博客,希望自己从基础开始。也是希望自己能够稍微系统来学习整合一下。因为之前从来都没系统学习过,都是用到啥查啥,先查啥就忘啥快,所以在此记录一下,以备以后查看。好了废话也不多说,进入正题。 

正文

1、类和对象

类的定义:具有相同属性和功能的对象的抽象集合。——脑门一闪,类其实也是个集合吗?

对类的认识:我觉得类像是个模具,用模具做出来的东西就是对象,当然现实中具体的模具也是对象。模具与做出来的东西更能体现继承,我觉得。

抽象,这咋说? 我理解的是,你能认识但不能描述的东西,就是抽象。比如:“人” 这个词,什么是人?你会说,有头发,眼睛,耳朵,手脚....啥的,这是在描述“人”的各个属性,如果有个模特站在你面前,你会指着这个模特说,看这就是人。那么我会马上对“人”这个词有深刻的影响。哦!这就是人啊!我可以这样说,这个模特就是“人”这个类的对象。这个模特活生生的对象能够对应上“人”这个类的各个属性。

继承:就想遗传,爷传爸,爸传子,子传... 龙生龙,凤生凤,老鼠的儿子会打洞!

多态: 话说全球那么多人,几乎没有一模一样的人,每个人都有自己的特点,长处,短处...龙生九子各有不同

就像我解答一道面试题写的那样

2.详述您对继承、多态、封装的认识。
继承:就好比一个有特异功能的爸爸,把这样的功能遗传给了他的儿子。
多态:就好比他儿子由于另外的基因加入,或者基于突变,又有了其他他爸爸没有的功能。
封装:就好比活字印刷术,不封装的代码就像在一块很大的木板上刻了很多字,而封装就好比将木板上的字一个个刻成一枚枚印章,用的时候排好版,直接用就可以了。
封装、多态、继承是面向对象的三个特点,这样使得面向对象有:更好的维护性,扩展性,复用性,灵活性,降低程序之间的耦合性。

 

类的实例:实例化就是创建对象的过程,使用new关键字来创建。一个从抽象到具体的过程

来看以下代码,最简单的,你肯定懂:

public class Cat
    {
        public string Name { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Cat cat = new Cat();
        }
    }

 

就是这句:Cat cat=new Cat();其实它做了两件事情,不知道你们知道不,我是现在才又知道的(原来肯定知道过,不过早已抛在千里之外了):之前我也知道,不看到这,我也忘记了,第一个声明Cat cat; cat是Cat类的对象这个时候是空的,new Cat();实例化了一直猫,然后将刚刚实例化的猫的引用交给了 cat 这个变量。cat保存的是一个指向new Cat()实例的引用对象。

2、goto:语句将程序控制直接传递给标记语句。

goto貌似在开发中从来没用过。Me too!话说用了很容易就将代码的运行逻辑搞的一踏糊涂,一个还好,10个,100个....好吓人

static void Main(string[] args)
        {
            int i = 0;
        repeat:            // the label
            Console.WriteLine("i: {0}", i);
            i++;
            if (i < 10)
                goto repeat;  // the dastardly deed

            Console.ReadLine();
        }

 

这是一个简单的用法满足条件的时候,跳转到标记repeat;

输出结果:

这有一篇关于goto的详细介绍:包括它的优缺点,应用场景。

http://www.cnblogs.com/IT-Bear/archive/2012/03/05/2380389.html

 

3、continue、break、return:C#编程语法中我们会经常碰到break ,continue, return这三个常用的关键字

break语句会使运行的程序立刻退出包含在最内层的循环或者退出一个switch语句。(立马跳出代码块,"{....}"这样的块)由于它是用来退出循环或者switch语句,所以只有当它出现在这些语句时,这种形式的break语句才是合法的。

如果一个循环的终止条件非常复杂,那么使用break语句来实现某些条件比用一个循环表达式来表达所有的条件容易得多。

            for (var i = 1; i <= 10; i++)
            {
                if (i == 6) break;
                Console.WriteLine(i);
            } //输出结果:12345

 

continue语句和break语句相似。所不同的是,它不是退出一个循环,而是开始循环的一次新迭代。

continue语句只能用在while语句、do/while语句、for语句、或者for/in语句的循环体内,在其它地方使用都会引起错误!do...while、while...do、foreach

            int[] intArr = { 27, 63, 45, 6, 25, 5, 678, 90 };
            foreach (var item in intArr)
            {
                if (item>100)
                {
                    continue;
                }
                Console.WriteLine(item);
            }
            // 27, 63, 45, 6, 25, 5, 90 

 

return语句就是用于指定函数返回的值。return语句只能出现在函数体内,出现在代码中的其他任何地方都会造成语法错误!

当执行return语句时,即使函数主体中还有其他语句,函数执行也会停止!

 

4、i++和++i,前者先用后加,后者先加后用

这个在学校学的时候就感觉好别扭,现在好久没看了又模糊了。可能这也是面试的时候很多公司愿意出的问题吧。

static void Main(string[] args)
        {
            int valueOne = 10;
            int valueTwo;
            valueTwo = valueOne++;
            Console.WriteLine("After postfix: {0}, {1}", valueOne,
            valueTwo);
            valueOne = 20;
            valueTwo = ++valueOne;
            Console.WriteLine("After prefix: {0}, {1}", valueOne,
            valueTwo);
            Console.ReadLine();
        }

 

 

再来看一个简单的小例子:

            int k = 0;
            int i = 3;
            k = ++i + (i++);
            Console.WriteLine("k={0},i={1}", k, i);

 

先来看如果i=3; return i++; 那么返回的是3;如果return ++i;那么返回的是4。

所以 ++i 现在i=4;表达式变为4+(4++),而4++是先用了再加 所以就是8++,而8++同理先返回8,i再++,i就为5。

当然此题解法可能不止一种,如果你有兴趣可以一起来探讨一下。

 

5、switch中的case可以这样写

static void Main(string[] args)
        {
            const int Democrat = 0;
            const int LiberalRepublican = 1;
            const int Republican = 2;

            int myChoice = LiberalRepublican;

            switch (myChoice)
            {
                case Democrat:
                    Console.WriteLine("You voted Democratic.\n");
                    break;
                case LiberalRepublican:
                case Republican:
                    Console.WriteLine("You voted Republican.\n");
                    break;
                default:
                    Console.WriteLine("You did not pick a valid choice.\n");
                    break;
            }
            Console.ReadLine();
        }

 

case LiberalRepublican:
case Republican:

符合这两个条件都会执行:

 Console.WriteLine("You voted Republican.\n");

 

6、三元运算符相当于if  else

static void Main( string[] args )
      {
         int valueOne = 10;
         int valueTwo = 20;
         int maxValue = valueOne > valueTwo ? valueOne : valueTwo;

         Console.WriteLine( "ValueOne: {0}, valueTwo: {1}, maxValue: {2}",
             valueOne, valueTwo, maxValue );
      }

 

int maxValue = valueOne > valueTwo ? valueOne : valueTwo;

这一句等同于一个if else

if (valueOne > valueTwo)
         {
             maxValue = valueOne;
         }
         else
         {
             maxValue = valueTwo;
         }

 

7、ref和out:两者都是按地址传递的,使用后都将改变原来参数的数值

rel可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所以你必须初始化一次。这个就是两个的区别,或者说就像有的网友说的,rel是有进有出,out是只出不进

先来看一下ref其效果是,当控制权传递回调用方法时,在方法中对参数的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。

示例:

static void Method(ref int i)
        {
            i = 44;
        }

        static void Main(string[] args)
        {
            int val = 0;
            Method(ref val);
            Console.WriteLine(val);              // val is now 44
            Console.ReadLine();
        }

 

传递到 ref 参数的参数必须最先初始化。这与 out 不同,后者的参数在传递之前不需要显式初始化。

再来看一下out:out 关键字会导致参数通过引用来传递。这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化。若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。

示例:

static void Method(out int i)
        {
            i = 44;
        }

        static void Main(string[] args)
        {
            int val;
            Method(out val);
            Console.WriteLine(val);              // val is now 44
            Console.ReadLine();
        }

 

尽管作为 out 参数传递的变量不必在传递之前进行初始化,但需要调用方法以便在方法返回之前赋值。

ref  out 关键字在运行时的处理方式不同,但在编译时的处理方式相同。因此,如果一个方法采用 ref 参数,而另一个方法采用 out 参数,则无法重载这两个方法。例如,从编译的角度来看,以下代码中的两个方法是完全相同的,因此将不会编译以下代码:

但是,如果一个方法采用 ref  out 参数,而另一个方法不采用这两类参数,则可以进行重载,如下所示:

        public void SampleMethod( int i) { } 
     public void SampleMethod(ref int i) { }

这样两个方法编译是可以成功的。

 

 8、String和string,之前几乎没区分过这两个,不过还是要注意一下。

在C#中,string 是 System.String 的别名,所以基本上在使用时是没有差别的。习惯上,我们把字符串当作对象时(有值的对象实体),我们用string。

而我们把它当类时(需要字符串类中定义的方法),我们用String,比如:string greet = String.Format("Hello {0}!", place)。

其实乱用也可以,只是这样概念上清楚一点。

另外string是C#保留字,不可用作变量名,String就不是了。 String 必须先引用 System命名空间。

也可以这样理解:string是C#中字符串类型String的反射,一种简化的书写方式,就像int对应于Int32一样,二者在C#中可通用。

再则String是一个类,string是一种数据类型。string是c#中的类,String是.net Framework的类(在c# IDE中不会显示蓝色)

c# string映射为.net Framework的String。如果用string,编译器会把它编译成String,所以如果直接用String就可以让编译器少做一点点工作。

 

9、重载运算符 

 先来看几行简单的代码:

static void Main(string[] args)
        {
             int x = 5;
             int y = 6;
             int sum = x + y;
             Console.WriteLine(sum);
            Console.ReadLine();
        }

 

一个int  sum=x+y; 加法运算。

稍微封装一下:

static void Main(string[] args)
        {
            int x = 5;
            int y = 6;
            int sum = Add(x, y);
            Console.WriteLine(sum);
        }
        static int Add(int x, int y)
        {
            return x + y;
        }

 

如果现在有一个类,需要得知两个类某个属性的和,我们可能会这样:

public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Person(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person("aehyok", 25);
            Person p2 = new Person("Leo", 24);
            int sum = Add(p1.Age, p2.Age);
            Console.WriteLine(sum);
        }
        static int Add(int x, int y)
        {
            return x + y;
        }
    }

 

我们再来改动一下:

class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person("aehyok", 25);
            Person p2 = new Person("Leo", 24);
            int sum = p1 + p2;
            Console.WriteLine(sum);
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Person(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }

        public static int operator +(Person p1,Person p2)
        {
            return p1.Age+p2.Age;
        }
    }

 

总结

 感觉自己的基础有点一塌糊涂吧,好好的补一下。这样一看原来很多基础的东西我从来都不清楚,或者见过然后忘记了。自己在此好好的进行整理总结一下,主要是为了自己复习巩固吧,也希望对某些人有一点作用,当然我的整理中可能存在很多问题,欢迎大牛们来指正。

 

posted on 2014-03-31 19:09  Aidou_dream  阅读(253)  评论(0)    收藏  举报

导航