C#学习记录

  最近想在周末闲着的时候使打算使用Unity做一款小游戏,于是昨天看了一下Unity官方的教程,简单的了解了Unity的使用界面,感觉蛮方便上手的,于是就有必要了解一番C#,方便快速上手Unity。
  目前看了大概一天的C#,有点不适应,大概了解了使用方式,如果有理解不到位的地方希望指出来,以下是个人目前觉得使用的时候需要注意的地方。
  PS:该文章可能会长期更新的。

  
  1、对象(Object)类型 ,是所有数据类型的基类。
  
  2、动态(Dynamic)类型,目前我个人使用感觉,有点类似于C++的auto关键字。
  
  3、内置的 引用类型有:object、dynamic 和 string,引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
  
  4、C#的字符串,是不能直接用[]去赋值修改,如以下代码是不能执行的,会显示只是可读属性,也就相当于一个const string。

         string a = "abc";
         a[0] = 'c';

  
  5、与C++不同,C#仅支持单继承,继承后通过使用关键字base,代表基类,然后进行初始化,如:

class A{
}

class B:A{
public B():base(){
}
}

  
  6、虽然C#只支持单继承,但是它可以多重继承,这时候就出现了接口(闻到了JAVA的味道),之前对接口这个概念不太了解,后面去了解了一下,接口这个概念,是只提供属性的声明,与方法的声明,而继承接口的类就必须去实现所有接口中的方法与属性。
  
  7、上面提及了一个词语,属性,属性是类、结构体、接口的一个成员变量,在C#中,把类、结构体、接口中的成员变量、方法称为域(Field),而属性就是域的扩展,属性可以通过访问器来修改私有域的值或获取,在我个人看来,就像在C++中,给一个私有变量提供一个get或者set操作的方法,而C#的属性,则相当于给一个变量绑定了set与get方法,get方法在属性中必须实现,而set方法可以实现或不实现,即,可读or可读可写,而实现set函数,获取set的值可通过value关键字,如以下代码:

		Program()
        {
            age = 10;
        }
        int age;
        public int Age{
            get { return age; }
            //or get; 这样默认返回 0
            set{
            	age=value;
            }
        }

  
  8、既然谈及接口,那么不得不说抽象类,这两者的区别,个人觉得,接口是一种规范,继承的类就必须要实现接口中的所有方法以及属性,而抽象类并不需要要你一定实现所有的方法,但是必须要实现抽象方法,在C++中即基类中的,抽象方法(virtual return_type func_name(parameters)=0)必须实现,在C#中抽象方法为abstract public return_type func_name(parameters)必须实现,而一般的成员函数,在继承抽象类的类中非必须实现,抽象类就像是类的共性,所有继承它的类都有着和它相似的地方,而接口是一种大家都要遵守的特殊类。
  
  9、C#中也有虚方法(不能声明为私有成员),同样是使用virtual关键字,通过虚方法与抽象类实现了多态,在派生类中实现的时候需要加override关键字。
  
  10、C#中也有预处理器指令,好像只是用于条件编译。
  
  11、特性,是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。我们可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
  这个具体使用以及作用看:http://www.runoob.com/csharp/csharp-attribute.html
  这让我想起了python的装饰器,当你执行一个函数,就会先调用装饰器,输出相应的信息,那么大概来说以下C#的特性
  AttributeUsage是用于自定义特性,可以设置特性具体用处,如设置在类、成员方法、属性、构造函数、成员变量,还可以添加多重特性之类。
  Conditional是用于条件编译,就比如以下的代码,如果有定义#define DEBUG那么就会使用具有该特性的成员方法、属性之类的,如果没有定义DEBUG,那么就不使用,具体可以在VS的DEBUG模式编译或者RELEASE模式编译看出区别。

[Conditional("DEBUG")]

  Obsolete则是一种带游限制是否调用的特性,如果有方法被标上该特性,并设置为true,那么编译不会通过…
  
  12、反射,这个功能不太了解,用途中的延迟绑定没明白是什么意思,说起延迟绑定,我就想起了python的延迟绑定,匿名函数lambda存储的时候并不会立即调用返回结果,而是使用到的时候才会去计算,而C#的这个我就不太了解了

  反射(Reflection)有下列用途:
    它允许在运行时查看特性(attribute)信息。
    它允许审查集合中的各种类型,以及实例化这些类型。
    它允许延迟绑定的方法和属性(property)。
    它允许在运行时创建新类型,然后使用这些类型执行一些任务。

  
  13、索引器(这让我想起了python或者是重载[]运算符),和访问器的用法大概类似,都用到get与set,而定义索引器的方法如下:

element-type this[int index] 
{
   // get 访问器
   get 
   {
      // 返回 index 指定的值
   }

   // set 访问器
   set 
   {
      // 设置 index 指定的值 
   }
}

  
  14、委托与事件,个人觉得,委托就是存放函数指针的一种形式,而委托的声明为:public delegate int FuncPTR (parameters);,这样我们就得到一个函数指针的类型,使用的话就直接FuncPTR p;,然后指向一个函数即可,除此之外,还可以进行多重委托,即:

//add与del为同类型函数,参数个数类型一致
	FuncPTR p=add;
	p+=del
	p(x,y)//会调用add与del
	

  上面是委托的形式,而事件,则是在委托类型的实例声明类型前加一个event即可,即public event FuncPTR funcs;,使用event后,在包含委托类的类外就不能对p(x,y)进行直接调用,我下面给一个简单的示例代码吧。

    class A
    {
        public delegate void FuncPTR();
        public event FuncPTR funcs;
        public void register(FuncPTR func)
        {
            funcs += func;
        }
        public void run()
        {
            if (funcs != null)
                funcs();
            else
                Console.WriteLine("no func !");
        }
    }

    class B
    {
        static void print()
        {
            Console.WriteLine("23333!");
        }
        
        static void Main()
        {
            A a = new A();
            B b = new B();
            a.register(delegate (){ B.print(); });
            //a.funcs();  会报错
            a.run();
        }
    }

  
  15、匿名函数的关键词为delegate
  
  16、方法参数用引用传递的话,在参数前面加关键字ref
  
  17、关键字out用于让一个方法返回多个值,而其用方是在参数前面加关键字out,使用带out关键字的参数必须在方法内进行初始化,也就相当于我们在C/C++中,为了得到多个返回值,而设置多个参数用于保存结果,为了让返回值不为null,我们要对其进行初始化。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值