您的位置:首页 > 编程语言 > C#

C#学习笔记6

2017-01-19 11:15 267 查看
1.结构:结构除了可以含有属性和字段,还可以包方法和构造器,但不能包含黠认(无参数}的构造器。有的时候(比如在实例化一个数组的时候)不会调用值类型的构造器,因为所有数组内存都转为用零来初始化,为了避免因为默认构造器只是偶尔调用而造成不一致,C#完全禁止了用户显式定义默认构造器,因为编译器会将声明时的实例字段赋值放到类型的构造器中进行。在构造器中必须对 struct中的所有字段进行初始化,如果没有做到这一点,就会产生编译错误,可查看Angle结构的代码。

2.结构的继承与接口:所有值类型都是密封的,除此之外,所有值类型都派生自system.ValueType,这意味着struct的继承链息是从object到ValueType到struct。值类型还能实现接口,许多接口都是实现接口框架固定组成部分,比如 IComparilble 和IFormattable。

3.装箱与拆箱:装箱就是把值类型变成引用类型,如下:

(1) 首先在堆中分配好内存,它将用于存放值类型的数据以及少许额外开销;

(2) 接着发生一次内存复制动作,栈上的值类型数据复制到堆上分配好的位置;

(3) 最后,对象或接口引用得到更新,指向堆上的位置;

  拆箱就是把引用类型变成值类型,如下:根据定义,CIL 指令 unbox 只是对堆上的数据进行解引用,并不包括从堆复制到栈的动作。但在 C#语言中,太多数时候紧接着在拆箱之后发生一次复制动作。装箱和拆箱之所以重要,是因为装箱去对性能和行为造成一些影响。开发者可以通过查看CIL,在一个特定的代码片段中统计 box/unbox 指令的数量。在BoxAndUnbox()中的代码就存在多次的装箱与拆箱,这样编写的代码是不合理。

4.枚举:枚举和其他值类型稍有不同,因为枚举的继承链是从System.ValueType到System.Enum,再到enum。

5.枚举与字符串的转换:枚举ToString()后会输出枚举标识符,使用Enum.Parse或Enum.TryParse方法可以把字符串转化为枚举,后一个方法是.Net4.0新增的泛型方法。此中我们也可以使用Enum.IsDefined()方法来检查一个值是否包含在一个枚举中。

6.枚举作为“位标志”使用:

(1)可以查看如下“FileAttributes“枚举的设定(即System.IO。FileAttributes的设定),作为位标志后,其值可以自由组合,所以可以使用Or运算符来联结枚举值。如本示例中BitFlag()方法的使用。当然枚举中的每个值不一定只对应一个标志,完全可以为常用的标志组合定义额外的枚举值。

(2)使用位标志类型的时候,位标志枚举应该包含[FlagsAttribute]这个特性,这个标志指出多个枚举值可以组合使用,此外,它改变了ToString()和Parse()方法的行为。例如为一个已用FlagsAttribute修饰了的枚举调用ToString()方法,会为已设置的每个枚举标志输出对应的字符串(如BitFlag2()的示例),而如果没有这个修饰,返回的就是组合后数值。

public struct Angle
{
public Angle(int hours, int minutes, int seconds)
{
Hours = hours;
Minutes = minutes;
Seconds = seconds;
}
public int Hours { get; set; }
public int Minutes { get; set; }
public int Seconds { get; set; }

public Angle Move(int hours, int minutes, int seconds)
{
return new Angle(Hours + hours, Minutes + minutes, Seconds + seconds);
}
}

[Flags]
public enum FileAttributes
{
ReadOnly = 1 << 0,
Hidden = 1 << 1,
System = 1 << 2,
Directory = 1 << 3,
Archive = 1 << 5,
Device = 1 << 6,
Normal = 1 << 7,
Temporary = 1 << 8,
SparseFile = 1 << 9,
ReparsePoint = 1 << 10,
Compressed = 1 << 11,
Offline = 1 << 12,
NotContentIndexed = 1 << 13,
Encrypted = 1 << 14
}

public void BitFlag()
{
string fileName = @"enumtest.txt";
FileInfo file = new FileInfo(fileName);
file.Attributes = FileAttributes.Hidden | FileAttributes.ReadOnly;
Console.WriteLine("{0} | {1} = {2}", FileAttributes.Hidden, FileAttributes.ReadOnly, (int)file.Attributes);
if ((file.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
{
throw new Exception("File is not hidden");
}
if ((file.Attributes & FileAttributes.ReadOnly) != FileAttributes.ReadOnly)
{
throw new Exception("File is not read-only");
}
//....
}

public void BitFlag2()
{
string fileName = @"enumtest.txt";
FileInfo file = new FileInfo(fileName);
file.Open(FileMode.Create).Close();
FileAttributes startingAttributes = file.Attributes;
file.Attributes = FileAttributes.Hidden | FileAttributes.ReadOnly;
Console.WriteLine("\"{0}\" output as \"{1}\"", file.Attributes.ToString().Replace(",", "|"), file.Attributes);
FileAttributes attributes;
Enum.TryParse(file.Attributes.ToString(), out attributes);
Console.WriteLine(attributes);
File.SetAttributes(fileName, startingAttributes);
file.Delete();
}

public void BoxAndUnbox()
{
int totalCount;
ArrayList list = new ArrayList();
Console.Write("Enter a number between 2 to 1000:");
totalCount = int.Parse(Console.ReadLine());
list.Add((double)0);
list.Add((double)1);
for (int i = 2; i < totalCount; i++)
{
list.Add((double)list[i - 1] + (double)list[i - 2]);
}
foreach (double num in list)
{
Console.Write("{0},", num);
}
}


----------------------以上内容根据《C#本质论 第三版》进行整理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: