解决方案 »
- 不显示删除回复显示所有回复显示星级回复显示得分回复 数据庫附加错误需要对 sysindexes 运行 DBCC CHECKTABLE?
- 如何把子窗体显示为最前
- c#.net的发布
- 在Winform(.Net2.0)中,在父窗体中打子窗体,怎么在子窗体中也能弹出属于父窗体的ContextMenuStrip呢??
- 请问大家好的多层架构的基类代码自动生成工具,实际开发中有用到的吗
- ***有关用C#写一个桌面背景图和屏保更换的问题***
- 急!! 哪位高手可以帮忙来分析一下这个关于web server的程序?
- 怎样才能把 NetworkStream 里的内容清空?
- NPOI 导入excel 的 奇葩问题
- 在RichTextBox中我怎样才能当前光标位于第几行?(RichTextBox是非自动换行)
- C#类,定义,使用——VS2008
- bool属性值绑定的时候,能否绑定"两个bool值的逻辑运算"?
而普通类的上下转换一直都支持..net4 加入这个功能就是为了让泛型类也保持这样的便利性.
void ProcessControls(IEnumerable<Control> ctrs){ }
没有协变,你就还得另外创建个实现了IEnumerable<Control>的集合。再比如:
Comparison<Control> ControlComparison =
(ctr1, ctr2) => ctr1.Left - ctr2.Left; List<TextBox> TextBoxList = new List<TextBox>()
{new TextBox(){Left=30},new TextBox(){Left=22}};
List<Label> LabelList = new List<Label>();
TextBoxList.Sort(ControlComparison);
LabelList.Sort(ControlComparison);
现在ControlComparison很简单,你可以每次在Sort方法里复制一份,但是如果它的逻辑很复杂就不行了。
或者要使用一个别人提供的,不知道内部实现的IComparer<Control>。
你看看你自己写的Animal和Dog,除了Dog继承了Animal之外一点点关系都没有。
额我知道你的意思,你看下这个,主要我是想实验一下,他们的animal的方法通过协变,究竟变了没有。someAnimals.ToList()[0].animal();
someDogs.ToList()[0].animal();
这个是用来解决设计问题,而不是根据这个能创建设计...
你反过来想,ruby/python/js会有协变和逆变吗?
所以someAnimals里面是Animal,调用的就是Animal的方法。
someDogs里面是Dog,调用的就是Dog的方法。
虽然都是同一个对象。
不好意思我看了很久,并且照着代码敲打,感觉没看出逆变和协变的效果...
比如这个
C# code
private void ProcessControls(IEnumerable<Control> ctrs)
{
}private void Action()
{
List<TextBox> textboxs = new List<TextBox>();
List<Label> LabelList = new List<Label>();
ProcessControls(textboxs);
ProcessControls(LabelList);
}难道这样就是协变了吗?如果这样就是协变了话,那么ProcessControls方法也就有比较大的限制吧?只能应用于textboxs和LabelList的共性
还有你说的第2个:
C# code
//如果这个很复杂的一个方法,然后下面的两个控件都是比较
Comparison<Control> ControlComparison = (ctr1, ctr2) => ctr1.Left - ctr2.Left; List<TextBox> TextBoxList = new List<TextBox>() { new TextBox() { Left = 30 }, new TextBox() { Left = 22 } };
List<Label> LabelList = new List<Label>(); TextBoxList.Sort(ControlComparison);
LabelList.Sort(ControlComparison);
这个是逆变吗?这个我看不懂= =...
你所说的“你可以每次在Sort方法里复制一份”
是指这样吗
TextBoxList.Sort((ctr1, ctr2) => ctr1.Left - ctr2.Left);
LabelList.Sort((ctr1, ctr2) => ctr1.Left - ctr2.Left);
----------------------------------------
这个是委托逆变。泛型在接口和委托两个地方支持变体(逆变和协变)
比如说TextBoxList,它的类型是List<TextBox>,所以Sort方法的参数类型就是Comparison<TextBox>(这是一个委托类型)。如果没有逆变,Comparison<Control>就不能转化为Comparison<TextBox>,也就无法使用ControlComparison委托对象。IComparer<T>同理,List<TextBox>的Sort方法要求参数类型为IComparer<TextBox>,如果没有逆变,就不能用一个IComparer<Control>对象作为它的参数。当然,你可以把比较器类实现为开放类型,让它可以产生其他类型的比较器。比如:
class MyControlComparer<T> : IComparer<T> where T:System.Windows.Forms.Control {}
当你需要排序任何Control派生类集合的时候可以方便地创建一个对应类型的比较器,但是你仍然需要创建新的比较器对象,而不能复用已有的比较器对象(或许这个比较器有很多的配置选项)。而如果是封闭实现
class MyControlComparer : IComparer<System.Windows.Forms.Control> { }
那就像上面所说的,没办法使用了。
非常感谢你的耐心回答!!!!!!但是貌似这些都是转换类中的某个方法??我看的还是很朦胧...即使以你的例子来代码写还是很朦胧...那我想问个问题
现在我的项目
有父抽象类Animal,有属性:吃,方法:叫
然后有2个子类:
猫:Cat,有属性:抓
狗:Dog,有属性:咬我想在程序初始化中先 Animal animal = null
然后在判断条件中如果是猫:
animal = new Cat;
如果是狗
animal = new Dog;但是,我想通过逆变来让animal可以使用到Cat或者Dog的属性。也就是整个代码中,我依然使用animal,而不用实例化cat或者dog来增加代码量
映射后的转换关系string[]->object[]和原始的转换关系string->object方向相同,这种变体叫做“协变”;如果方向相反,就叫“逆变”。
string->object的转换关系可以映射为IComparer<object>->IComparer<string>,和原来的方向相反,所以它是“逆变”。上面这种string->object的转换,本质上是“派生类引用到基类引用的转换”。除了这种转换,还有其他转换,比如基元类型之间的转换,像byte->short->int->long,以及用户自定义的转换。在.NET中,只有派生类引用到基类引用的转换支持变体,其他两种不支持。
所以虽然byte可以隐式转换为int,但是byte[]不能转换为int[];同样,IEnumerable<byte>不能转换为IEnumerable<int>。变体不仅存在于泛型中,也存在于其他地方,比如上面例子中的数组,另外就是委托和函数的绑定。至于变体体现代码重用这个很明显啊,它可以将原有类型的转换自动映射到基于原有类型的新类型上,这样你同一份代码就可以用在更多的地方。(如果没有变体,这些新类型之间就没有转换关系,需要为每种类型单独写代码。)
Animal和Cat不能互相转换?只能针对类型?对象之前不能转换么
就是 dog = animal ;
既然 People cnp = new ChinesePeople(); 成立List<Prople> cnp = new List<ChinesePeople>(); 是很自然的事情。不过遗憾的是,在C# 4以前这么写不行。现在行了,难道还有什么需要研究的呢?