zoukankan      html  css  js  c++  java
  • C#语法杂谈

    1. 值类型和引用类型

    1.1 值类型

    比如int,float,struct等,和C/C++中的变量差不多,但编译器会强制你必须先初始化再使用,避免一不小心使用了未初始化的变量。

    1.2 引用类型

    class是引用类型,其默认行为类似于引用或指针(?但可以通过重载函数改变其默认行为?)。

    注:尽管教科书上一般将class归为引用类型,但我倾向于将它们看作指针类型,一方面是因为它们的行为更像是指针,另一方面是便于与函数引用参数ref区分开。

    比如你定义了一个class MyClass,现在想要一个MyClass类型的变量,那么必须这样:

    MyClass myClass = new MyClass();

    而不能简单地MyClass myclass完事。

    又如语句MyClass anotherMyClass = myClass,其效果等价于指针赋值。

    1.3 总结

    不管是值类型还是引用类型,编译器都强制必须先初始化后使用,因此在定义和初始化上两者并无明显区别。它们的主要区别在于赋值运算符和函数参数传递时。

    2. 变量初始化

    因为编译器强制变量必须初始化后再使用,因此如下代码是无法通过编译的:

    int i;
    if(condition) {
        i = 1;
    }
    Console.WriteLine(i);

    由于condition的不确定,编译器无法确认i是否得到了初始化。但下面代码可以:

    int i;
    if(true) {
        i = 1;
    }
    Console.WriteLine(i);

    上面的代码中,编译器可以确定i得到了初始化。类似下面的代码也是可以的:

    int i;
    for(;;)
    {
        i = 1;
     break; } Console.WriteLine(i);

     P.S. 因为这个强制初始化要求,所以函数参数必须能够具备out属性用于传递一个未经初始化的变量,以避免不必要的初始化。

    又P.S. 从上面代码中可以看出,圣书《C#入门经典》关于for循环体中变量作用域的解释并不正确,至少第五版是如此。书中那段不能通过编译的代码,主要原因是编译器无法确认for循环是否一定执行(尽管程序员可以确认),也就无法确认变量是否在for循环中得到了初始化,而不是因为书中那段估计作者自己都看不明白的解释(中文版第五版,正文p123-124)。

    3. 数组

    3.1 如上所述,数组也必须初始化后再使用,例如int[] array = new int[3]。但是可以省略数组每个元素的初始化:编译器会将它们初始化为默认值。

    3.2 多维数组

    其含义等价于C语言的多维数组,但语法不同,例如int[,] array = new int[3,4]。

    3.3 数组的数组

    数组的数组可以理解为指针数组,数组的每个元素都是个“指针”,指向另一个数组。所以初始化也分两级。例如:

    int[][] array = new int[][] { new int[3], new int[4] };

    4. 函数参数

    void test(MyClass myClass)
    {
    myClass.dosomething();
    myClass = new MyClass(); }
    void test(ref MyClass myClass) {
    myCLass.dosomething();
    myClass = new MyClass(); }

    如上文所述,class的行为像指针。所以形参myClass上的dosomething()是作用于实参上的。非ref参数的test函数中,myClass=new MyClass()会覆盖形参但不会影响实参;而ref参数的test函数中,myClass=new MyClass()会同时覆盖掉实参。

    5. 委托

    简单情况下,委托的定义类似于class,使用起来类似于函数指针。

    // 1. 定义一个委托“类”
    //     下面这条语句一般位于那些可用来放置class定义的地方
    delegate void MyDelegate();
    // 2. 声明(并在需要时初始化)一个委托“类”的实例
    MyDelegate myDelegate = MyFunction;
    // 3. 使用该“类”的实例:通过委托调用函数
    myDelegate();

    6. virtual、override和new

    如果你想要多态,在基类中使用virtual,在继承类中使用override;

    如果你想要重新实现,在继承类中使用new。

    7. 属性

    举个栗子:很多论坛对长贴提供直接输入分页进行跳转的功能,基于C/C++/C#程序员的骄傲,在代码内部分页总是从0开始计数,但显示值总是从1开始计数:

    class MyClass
    {
        private int _page;
        public int page
        {
            get
            {
                return _page + 1;
           }
            set
            {
                _page = value - 1;
            }
        }
    }

    属性功能上类似于下面代码,但让你可以用访问成员变量的语法去访问属性。

    // C#伪代码
    public int get_page()
    {
        return _page + 1;
    }
    public void set_page(int value)
    {
        // value实际上是C#关键字,
        // 在set方法中使用。
        _page = value - 1;
    }
  • 相关阅读:
    Ext JS学习第三天 我们所熟悉的javascript(二)
    Ext JS学习第二天 我们所熟悉的javascript(一)
    Ext JS学习第十七天 事件机制event(二)
    Ext JS学习第十六天 事件机制event(一)
    Ext JS学习第十五天 Ext基础之 Ext.DomQuery
    Ext JS学习第十四天 Ext基础之 Ext.DomHelper
    Ext JS学习第十三天 Ext基础之 Ext.Element
    Ext JS学习第十天 Ext基础之 扩展原生的javascript对象(二)
    针对错误 “服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF” 的原因分析
    C# 使用HttpWebRequest通过PHP接口 上传文件
  • 原文地址:https://www.cnblogs.com/byeyear/p/5136581.html
Copyright © 2011-2022 走看看