CSharpThinking
来源:互联网 发布:知豆电动汽车价格表 编辑:程序博客网 时间:2024/06/04 00:33
实践是检验真理的捷径。
本章主要是理解C#中的协变和逆变的关系,对今后理解泛型会有很大帮助。
1.协变与逆变的概念及代码说明。
C#1:数组是强类型,强类型不允许内部数据不能相互转换。C#2中引入了对协变与逆变的限制,而C#4中又适当放宽了政策,不过这一切对数组没有任何影响,不过可以用一系列的接口和集合代替数组。
1 Stephen[] MySelf = new Stephen[1]; 2 MySelf[0] = new Stephen() { Name = "name1", Name2 = "name2" }; 3 StephenBase[] MyBase = MySelf; // 协变 4 Stephen[] OtherMe = (Stephen[])MyBase; // 逆变 5 6 ... 7 8 public class StephenBase 9 {10 public StephenBase() { }11 public string Name { get; set; }12 }13 14 public class Stephen : StephenBase15 {16 public Stephen()17 {18 19 }20 21 public string Name2 { get; set; }22 }
委托的协变和逆变
逆变:其中void KeyPressEventHandler(object sender, KeyPressEventArgs e) 继承自 void EventHandler(object sender, EventArgs e)
1 void LogPlainEvent(object sender ,EventArgs e)2 {3 Console.WriteLine("An event occurred!");4 }5 6 Button btn = new Button();7 btn.Click += LogPlainEvent; // 委托逆变8 btn.KeyPress += LogPlainEvent; // 委托逆变
协变:
1 delegate Stream StreamFactory(); 2 3 StreamFactory sf = GenerateMeoryStream; // 委托协变 4 using (Stream s = sf()) 5 { 6 int data; 7 while ((data = s.ReadByte()) != -1) 8 { 9 Console.WriteLine(data);10 }11 } 12 13 static MemoryStream GenerateMeoryStream()14 {15 byte[] buffer = new byte[16];16 for (int i = 0; i < buffer.Length; i++)17 {18 buffer[i] = (byte)i;19 }20 return new MemoryStream(buffer);21 }
注:协变和逆变是指从基类转换成子类或从子类转换到基类。
2.有趣的是:当把一个子类转换成基类,又紧接着转换成了子类,新子类中完全包含旧子类的全部信息,而不仅仅是基类的信息。
1 Stephen[] MySelf = new Stephen[1];2 MySelf[0] = new Stephen() { Name = "name1", Name2 = "name2" }; 3 StephenBase[] MyBase = MySelf; // 协变4 Stephen[] OtherMe = (Stephen[])MyBase; // 逆变5 6 Console.WriteLine("ChildName: " + OtherMe[0].Name2);7 Console.ReadLine();
接口继承也会在二次复原转换后依然保留原始信息。
1 public static void InterfaceTest() 2 { 3 HelloStephen stephen = new HelloStephen() 4 { 5 Email = @"Stephen.Cui@Emerson.com", 6 Oicq = @"229063661", 7 IsAlive = true 8 }; 9 10 IHelloStephen istephen = (IHelloStephen)stephen;11 HelloStephen targetStephen = HelloStephen.FindStephen(istephen);12 13 Console.WriteLine("Is Stephen alive ?");14 Console.WriteLine(targetStephen.IsAlive);15 Console.WriteLine("Contact Me ? To : " + targetStephen.Email + " Or QQ : " + targetStephen.Oicq);16 }
1 /// <summary> 2 /// Descrption: 3 /// IStephen Interface 4 /// </summary> 5 public interface IHelloStephen 6 { 7 string Email { get; set; } 8 string Oicq { get; set; } 9 bool IsAlive { get; set; }10 }11 12 public class HelloStephen : IHelloStephen13 {14 #region IHelloStephen15 string _Email;16 string _Oicq;17 bool _isAlive;18 19 public bool IsAlive20 {21 get { return _isAlive; }22 set { _isAlive = value; }23 }24 public string Email25 {26 get { return _Email; }27 set { _Email = value; }28 }29 public string Oicq30 {31 get { return _Oicq; }32 set { _Oicq = value; }33 }34 #endregion35 36 #region HelloStephen37 public string MyCNBlogs { get; set; }38 #endregion39 40 #region Method41 public static HelloStephen FindStephen(IHelloStephen stephen)42 {43 return (HelloStephen)stephen ?? new HelloStephen() { IsAlive = false };44 }45 #endregion46 }
3.方法组转换。
C#1中如果要创建一个委托实例,就必须同时指定委托类型和要采取的操作;C#2提供从方法组(一个方法名,表达式)到一个兼容类型的隐式转换。
1 // C#12 Thread t = new Thread(new ThreadStart(MyMethod));3 4 // C#25 Thread t = new Thread(MyMethod);
4.C#1与C#2中委托协变逆变的不同之处。
存在不兼容的风险:
1 EventHandler general = new EventHandler(Event);2 KeyPressEventHandler key = new KeyPressEventHandler (general); // C#1报错,而C#2不报错。
C#1要求两个委托的类型签名必须匹配。
本文多数实例均引自《C# in Depth Second Edition》
<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
- CSharpThinking
- CSharpThinking
- CSharpThinking
- C#跨线程修改控件——从MSIL和汇编看Invoke, 多线程, 事件与事件委托
- 更新sdk后,点击sdk管理器报出location of the android sdk has not setup in the prefrences
- fork()和vfork()函数
- 黑马程序员——————java中的继承和多态
- C#调用ATL COM
- CSharpThinking
- strcmp和memcpy比较
- C语言小机器人
- 有关DBN的一点小心得
- mini2440 DM9000 网卡驱动移植
- 使用COM简单操作IE
- 多线程实现大量数据加载时的等待画面
- 自定义控件修改图标
- 关于cocos2dx 2.0.3 及以上找不到org.cocos2dx.lib库的解决