1.索引器
1.1.索引器方法
public class PersonCollection : IEnumerable
{
private ArrayList arPeople = new ArrayList();
// 类的自定义索引器
public Person this[int index]
{
get{return (People)arPeople[index];}
set{arPeople.Insert(index, value);};
}
...
}
1.2.使用字符串值索引对象
public class PersonCollection : IEnumerable
{
private Dictionary<string, Person> listPeople = new Dictionary<string, Person>();
public Person this[string name]
{
get{ return listPeople[name];}
set{ listPeople[name] = value;}
}
public void ClearPeople()
{
listPeople.Clear();
}
public int Count
{
get{ return listPeople.Count;}
}
IEnumerator IEnumerable.GetEnumerator()
{
return listPeople.GetEnumerator();
}
}
static void Main()
{
PersonCollectioni myPeople = new PersonCollection();
myPeople["Homer"] = new Person("Homer", "Simpson", 40);
myPeople["Marge"] = new Person("Marge", "Simpson", 38);
Person homer = myPeople["Homer"];
Console.WriteLine(homer.ToString());
Console.ReadLine();
}
1.3.重载索引器方法
public sealed class DataTableCollection : InternalDataCollectionBase
{
// 重载的索引器
public DataTable this[string name]{get;}
public DataTable this[string name, string tableNamespace]{get;}
public DataTable this[int index]{get;}
}
1.4.多维的索引器
public class SomeContainer
{
private int[,] my2DintArray = new int[10, 10];
public int this[int row, int column]
{}
}
1.5.在接口类型上定义索引器
public interface IStringContainer
{
string this[int index]{get; set;}
}
class SomeClass : IStringContainer
{
private List<string> myStrings = new List<string>();
public string this[int index]
{
get{return myStrings[index];}
set{myStrings.Insert(index, value);}
}
}
C#操作符可重载性
+, -, !, ~, ++, --, true, false 可重载
+, -, *, /, %, &, |, ^, <<, >> 可重载
==, !=, <, >, <=, >= 可重载【<和>, <=和>=, == 和 != 重载时要一起】
[] 索引器提供了类似的功能,故,不再支持重载
() 自定义转换方法提供了同样的功能,故,不再支持重载
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= 不可重载,但相关二元操作符重载时,也随之具备新功能
operator 允许自定义类型对内建操作符做出不同反应,且只可与static关键字联合使用。
public class Point : IComparable
{
...
public static Point operator+(Point p1, Point p2)
{
return new Point(p1.X + p2.X, p1.Y + p2.Y);
}
public static Point operator-(Point p1, Point p2)
{
return new Point(p1.X-p2.X, p1.Y-p2.Y);
}
// C#中不能独立重载前后递增/递减。
public static Point operator++(Point p1)
{
return Point(p1.X+1, p1.Y+1);
}
public static Point operator--(Point p1)
{
return new Point(p1.X-1, p1.Y-1);
}
// System.Object.Equals()可以重写,实现引用类型间基于值的比较
// 如果选择重写Equals和与之密切相关的System.Object.GetHashCode,则,再重载==和!=意义不大
public override bool Equals(object o)
{
if(o == null) return false;
return o.ToString() == this.ToString();
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
public static bool operator==(Point p1, Point p2)
{
return p1.Equals(p2);
}
public static bool operator!=(Point p1, Point p2)
{
return !p1.Equals(p2);
}
// 重载比较操作符
public int CompareTo(Point other)
{
if(this.X > other.X && this.Y > other.Y)
{
return 1;
}
if(this.X < other.X && this.Y < oher.Y)
{
return -1;
}
else
{
return 0;
}
}
public static bool operator<(Point p1, Point p2)
{
return (p1.CompareTo(p2) < 0);
}
public static bool operator>(Point p1, Point p2)
{
return (p1.CompareTo(p2) > 0);
}
public static bool operator<=(Point p1, Point p2)
{
return (p1.CompareTo(p2) <= 0);
}
public static bool operator>=(Point p1, Point p2)
{
return (p1.CompareTo(p2) >= 0);
}
}
//
Point p1 = new Point(10, 10);
Point p2 = new Point(10, 10);
Point p3 = p1 + p2;
Point p4 = Point.operator+(p1, p2);
// 因为重载了+和-,故+=, -=自动具备重载后的表现
1.
C#允许我们构建能使用户类型响应()操作符的自定义强制类型转换例程。
2.
public struct Rectangle
{
public int Width{get; set;}
public int Height{get; set;}
public Rectangle(int w, int h) : this()
{
Width = w;
Height = h;
}
public void Draw()
{
for(int i = 0; i < Height; i++)
{
for(int j = 0; j < Width; j++)
{
Console.Write("*");
}
Console.WriteLine();
}
}
public override string ToString()
{
return string.Format("[Width={0}; Height={1}]", Width, Height);
}
}
public struct Square
{
public int Length{get; set;}
public Square(int l) : this()
{
Length = l;
}
public void Draw()
{
for(int i = 0; i < Length; i++)
{
for(int j =0; j < Length; j++)
{
Console.Write("*");
}
Console.WriteLine();
}
}
public override string ToString()
{
return string.Format("[Length={0}]", Length);
}
public static explicit operator Square(Rectangle r)
{
Square s = new Square();
s.Length = r.Height;
return s;
}
public static explicit operator Square(int sideLength)
{
Square newSq = new Square();
newSq.Length = sideLength;
return newSq;
}
public static explicit operator int(Square s)
{
return s.Length;
}
public static implicit operator Rectangle(Square s)
{
Reactangle r = new Rectangle();
r.Height = s.Length;
r.Width = s.Length * 2;
return r;
}
}
3.
转换例程使用C# operator,结合使用explicit或implicit 且 必须定义为静态的。
传入参数是要转换的实体,操作符类型是转换后的实体。
允许你在不直接修改原始类型下,为类或结构添加新的方法或属性。
1.定义扩展方法
必须把方法定义在静态类中。故,每一个扩展方法须声明为静态的。
所有扩展方法都要使用this对第一个参数【且仅对第一个参数】进行修饰。
2.
static class MyExtensions
{
// 扩展方法的第一个参数表示被拓展的类型。需要用this修饰。
// 后续其它参数,即为方法的普通传入参数
public static void DisplayDefiningAssembly(this object obj)
{
Console.WriteLine("{0} lives here:=>{1}\n", obj.GetType().Name, Assembly.GetAssembly(obj.GetType()).GetName().Name);
}
public static int ReverseDigits(this int i)
{
char[] digits = i.ToString().ToCharArray();
Array.Reverse(digits);
string newDigits = new string(digits);
return int.Parse(newDigits);
}
}
3.导入扩展方法
在定义包含扩展方法的类时,应将其定义在.NET命名空间中。
如果该命名与使用扩展方法的命名空间不同,就需在使用扩展方法的哪里使用using关键字。
4.扩展实现了指定接口的类型
static class AnnoyingExtensions
{
public static void PrintDataAndBeep(this System.Collections.IEnumerable iterator)
{
foreach(var item in iterator)
{
Console.WriteLine(item);
Console.Beep();
}
}
}
static void Main()
{
Console.WriteLine("***xxx***\n");
string[] data = {"1", "2", "3"};
data.PrintDataAndBeep();
Console.WriteLine();
List<int> myInts = new List<int>(){10, 15, 20};
myInts.PrintDataAndBeep();
Console.ReadLine();
}
1.定义匿名类型
当定义一个匿名类型时,需使用关键字var和对象初始化语法。
static void BuildAnonType(string make, string color, int currSp)
{
var car = new {Make = make, Color = color, Speed = currSp};
Console.WriteLine("You have a {0} {1} going {2} MPH", car.Color, car.Make, car.Speed);
Console.WriteLine("ToString() == {0}", car.ToString());
}
2.
所有的匿名类型都自动继承System.Object,
匿名类型的类型名完全由编译器决定。
3.创建由匿名类型组成的匿名类型
var purchaseItem = new
{
TimeBought = DateTime.Now,
ItemBought = new {Color = "Red", Make = "Saab", CurrentSpeed = 55},
Price = 34.000
};
1.编译时,须指定 /unsafe
2.进行指针操作的区域用 unsafe{} 包围。
class Program
{
static void Main(string[] args)
{
unsafe
{
// 可直接使用指针区域
}
}
}
// 不安全的结构,仅可用于unsafe上下文中
unsafe struct Node
{
public int Value;
public Node* Left;
public Node* Right;
}
// 这个结构可以用在非unsafe上下文,但结构Node2*成员只能用在unsafe上下文。
public struct Node2
{
public int Value;
// 只能在unsafe上下文访问
public unsafe Node2* Left;
public unsafe Node2* Right;
}
// 此函数只有在不安全上下文才能被调用
unsafe static void SquareIntPointer(int* myIntPointer)
{
*myIntPointer *= *myIntPointer;
}
unsafe
{
int *p1, *p2;// X
int* p1, p2;// C#中这里和C/C++不同。
}
在不安全上下文中,可能需要声明一个直接从调用栈分配内存的本地变量。
unsafe static void UnsafeStackAlloc()
{
char* p = stackalloc char[256];
for(int k = 0; k < 256; k++)
p[k] = (char)k;
}
使用fixed关键字
class PointRef
{
public int x;
public int y;
public override string ToString()
{
return string.Format("({0}, {1})", x, y);
}
}
class MyTest
{
unsafe public static void UseAndPinPoint()
{
PointRef pt = new PointRef();
pt.x = 5;
pt.y = 6;
// 在适当位置固定pt以免GC除去
fixed(int* p = &pt.x)
{
// 在此使用int*变量
}
}
}
任何时候在不安全代码上下文中与引用类型交互,都要固定该引用。
sizeof在不安全代码中用于获取类型尺寸大小。