c#知识点(1)
1.
在C 和C++中用0 来表示假其它任何非0 的式子都表示真这种不正规的表达在C#中已经被废弃了在C#中true 值不能被其他任何非零值所代替
在其它整数类型和布尔类型之间不再存在任何转换将整数类型转换成布尔型是不合法的。
bool x = 1 //错误不存在这种写法只能写成x=true 或 x=false
2.
常量修饰符可以是
.. new
.. public
.. protected
.. internal
.. private
3.
隐式枚举转换允许把十进制整数0转换成任何枚举类型对应其它的整数则不存在这种隐式转换。
隐式引用转换包括以下几类
.. 从任何引用类型到对象类型的转换
.. 从类类型s 到类类型t 的转换其中s 是t 的派生类
.. 从类类型s 到接口类型t 的转换其中类s 实现了接口t
.. 从接口类型s 到接口类型t 的转换其中t 是s 的父接口
从元素类型为Ts 的数组类型S 向元素类型为Tt 的数组类型T 转换这种转换需
要满足下列条件
.. S 和T 只有元素的数据类型不同但它们的维数相同
.. Ts 和Tt 都是引用类型
.. 存在从Ts 到Tt 的隐式引用转换
.. 从任何数组类型到System.Array 的转换
.. 从任何代表类型到System.Delegate 的转换
.. 从任何数组类型或代表类型到System.ICloneable 的转换
.. 从空类型null 到任何引用类型的转换
4.
显式引用转换包括:
.. 从对象到任何引用类型
.. 从类类型S 到类类型T 其中S 是T 的基类
.. 从类类型S 到接口类型T 其中S 不是密封类而且没有实现T
.. 从接口类型S 到类类型T 其中T 不是密封类而且没有实现S
.. 从接口类型S 到接口类型T 其中S 不是T 的子接口
从元素类型为Ts 的数组类型S 到元素类型为Tt 的数组类型T 的转换这种转换
需要满足下列条件:
.. S 和T 只有元素的数据类型不同而维数相同
.. Ts 和Tt 都是引用类型
.. 存在从Ts 到Tt 的显式引用转换.
.. 从 System.Array 到数组类型
.. 从System.Delegate 到代表类型
.. 从System.ICloneable 到数组类型或代表类型
显式引用转换发生在引用类型之间需要在运行时检测以确保正确,
为了确保显式引用转换的正常执行要求源变量的值必须是null 或者它所引用的对象的类型可以被隐式引用转换转换为目标类型否则显式引用转换失败将抛出一个InvalidCastException 异常。
不论隐式还是显式引用转换虽然可能会改变引用值的类型却不会改变值本身。
5.
在C#中:
.. 正零和负零被认为是相等的
.. 负无穷被认为小于其它任何值只是等于另一个负无穷
.. 正无穷被认为大于其它任何值只是等于另一个正无穷
枚举类型比较操作符简单地比较两个操作数的基类型值。
6.
下列条件之一成立则认为两个字符串值相等
.. 两个字符串值都为null
.. 两个字符串是字符串长度相同对应的字符序列也相同的非空字符串。
注意字符串等价操作符比较的是两个字符串的值而不是字符串引用当两个单独的字符串实例含有相同的字符串序列则认为这两个字符串的值相等引用类型
等价操作符可以用于比较两个字符串引用不是比较两个字符串的值。
7.
new 操作符用于创建一个新的类型实例它有三种形式:
.. 对象创建表达式用于创建一个类类型或值类型的实例
.. 数组创建表达式用于创建一个数组类型实例
.. 代表创建表达式用于创建一个新的代表类型实例
new 操作符暗示一个类实例的创建但不一定必须暗示动态内存分配这和C++中对指针的操作不同。
8.
c 和c++语言允许switch 语句中case 标签后不出现break 语句,但c#不允许这样,它要求每个标签项后使用break 语句或跳转语句goto,即不允许从一个case 自动遍历到其
它case 否则编译时将报错。
8.
using System;
class Test
{
int x;
static int y;
void F() {
x = 1; // 正确,等价于this.x = 1
y = 1; // 正确,等价于Test.y = 1
}
static void G() {
x = 1; // 错误不能访问 this.x
y = 1; // 正确,等价于Test.y = 1
}
static void Main() {
Test t = new Test();
t.x = 1; // 正确
t.y = 1; // 错误不能在类的实例中访问静态成员
Test.x = 1; // 错误不能按类访问非静态成员
Test.y = 1; // 正确
}
}
类的非静态成员属于类的实例所有每创建一个类的实例都在内存中为非静态成员开辟了一块区域;而类的静态成员属于类所有为这个类的所有实例所共享无
论这个类创建了多少个副本一个静态成员在内存中只占有一块区域。
9.
.. 一个类的构造函数通常与类名相同
.. 构造函数不声明返回类型
.. 一般地构造函数总是public 类型的如果是private 类型的表明类不能被实例化这通常用于只含有静态成员的类
.. 在构造函数中不要做对类的实例进行初始化以外的事情也不要尝试显式地调用构造函数
10.
C#中方法的参数有四种类型:
.. 值参数不含任何修饰符
.. 引用型参数以ref 修饰符声明
.. 输出参数以out 修饰符声明
.. 数组型参数以params 修饰符声明
11.
如果形参表中包含了数组型参数那么它必须在参数表中位于最后;另外参数只允许是一维数组比如string[]和string[][]类型都可以作为数组型参数而string[,]
则不能最后数组型参数不能再有ref 和 out 修饰符。
12.
在C#中,如果你在声明一个方法的时候用了virtual这个关键字,那么,在派生类中,你就可以使用override或者new关键字来弃用它或是忽略它.如果你在父类中用了virtual这个关键字,而在其派生类中又没有用override或new关键字,而直接引用一个同名方法的话,编译器将会报错,并将以new方式,即忽略派生类中的方法的方式来运行.下面的例子可以帮助你来理解:
000: // Versioning/versioning.cs
001: public class MyBase
002: {
003: public virtual string Meth1()
004: {
005: return "MyBase-Meth1";
006: }
007: public virtual string Meth2()
008: {
009: return "MyBase-Meth2";
010: }
011: public virtual string Meth3()
012: {
013: return "MyBase-Meth3";
014: }
015: }
016:
017: class MyDerived : MyBase
018: {
019: public override string Meth1()
020: {
021: return "MyDerived-Meth1";
022: }
023: public new string Meth2()
024: {
025: return "MyDerived-Meth2";
026: }
027: public string Meth3() // 系统在这里将会有一个警告,并且将会隐藏方法Meth3()
028:
029:
030: {
031: return "MyDerived-Meth3";
032: }
033:
034: public static void Main()
035: {
036: MyDerived mD = new MyDerived();
037: MyBase mB = (MyBase) mD;
038:
039: System.Console.WriteLine(mB.Meth1());
040: System.Console.WriteLine(mB.Meth2());
041: System.Console.WriteLine(mB.Meth3());
042: }
043: }
输出:
MyDerived-Meth1
MyBase-Meth2
MyBase-Meth3
可以很明显地看出来,后两个new关键字的输出是父类中的方法的输出,所以可以看出,new这个关键字的作用是如果在以前的版本中有这个方法,就沿用以前的方法,而不用我现在方法内容.而virtual的方法的作用正好相反,它的作用是如果在父类中有这样一个方法,则用我现在写的方法内容,让以前的滚蛋!不过,这里用new好象不太好,让人误解(糟了,盖痴又要打我了!&*%$#@).
如果你把第037行去掉,把039-041中的mB全部改为mD,输出又变为:
MyDerived-Meth1
MyDerived-Meth2
MyDerived-Meth3
这又说明了什么呢,说明了派生类的对象只有在被父类重塑的时候,override和new关键字才会生效.呵呵,这样说的确有点难以理解,大家只有自己动手,才能搞清楚这其中的机关,所谓"实践是检验C#的唯一标准",哈哈!
10.c#中的结构非常类似于类,但它是值类型,而不是引用类型,其结构成员在默认状态下是私有的,结构不支持继承,也不能从任何类中派生,唯一的异常是结构派生于类System.Object,因此结构也可以访问System.Object的方法,甚至可以重写System.Object中的方法-例如重写ToString()方法,实际上继承是间接的:结构派生于System.ValueType,System.ValueType派生于System.Object,ValueType并没有添加自己的新方法,但提供了Object的一些更适合值类型的重写方法;把结构作为ref参数传递给方法,可以避免因复制数据带来的性能损失。
为结构定义构造函数必须指定参数,在结构中初始化实例字段是错误的,有构造函数。
11.c#有15个预定义类型,其中有13个值类型和2个引用类型(string和Object)
12.c#认为byte类型和char类型完全不同(在强调类型的安全时),它们之间的编程必须明确写出,byte的类型在默认的情况下是无符号的,其有符号的版本有一个特殊的名称sbyte。
13.String对象保留在堆上,而不是堆栈上;因此把一个字符串变量赋给另一个字符串时,会得到对内存中同一个字符串的两个引用。然后,修改其中的一个字符串,注意这会创建一个完全新的string对象,而另一个字符串没有改变。
14.静态只读字段不能在实例构造函数中设置,也不能在静态构造函数中实例化只读字段;唯一例外的规则是:如果当变量声明为一个类或结构的字段时,给变量指定了一个值,就不能重新设置只读字段的值,而可以在构造函数中实例化只读字段。只读变量不能作为引用或输出参数传递给方法,但在构造函数中除外。
15.常量总是静态的,但是在声明时不允许包含static;只读字段可以用来初始化常量。
16.只能在不安全的代码中使用sizeof运算符。
17.在System.Object中,ToString()只显示类名,可以重写它。
18.重载方法的签名必须不同--即参数的名称、个数和类型必须不同,只有返回类型不同是不够的。
19.静态构造函数没有定义访问修饰符,其他c#代码从来不调用它,但在加载类时,总是由.NET运行时调用它,所以像public和private这样的修饰符就没有意义了。同样静态构造函数不能带有任何参数,一个类也只能有一个静态构造函数。
20.Const值是隐式静态的,对它必须用静态成员的语法,但如果显示声明它,即加上static则式错误的。
21.readonly字段的赋值只能在构造函数中,如果要把readonly字段设置为静态,就必须显式声明,在构造函数中不必给readonly字段赋值,如果没有赋值,它的值就是其数据类型的默认值。