我没有参加PDC 2008,但我听到一些消息称C#4.0被宣布支持Generic协方差和反差异.也就是说,List<string>可以分配给List<object>.怎么会这样?
在Jon Skeet的C#深度书中,解释了为什么C#泛型不支持协方差和反方差.它主要用于编写安全代码.现在,C#4.0改为支持它们.它会带来混乱吗?
有人知道有关C#4.0的细节可以给出一些解释吗?
似乎List对象不能存储在C#中的List变量中,甚至不能以这种方式显式转换.
List<string> sl = new List<string>();
List<object> ol;
ol = sl;
Run Code Online (Sandbox Code Playgroud)
结果无法隐式转换System.Collections.Generic.List<string>为System.Collections.Generic.List<object>
然后...
List<string> sl = new List<string>();
List<object> ol;
ol = (List<object>)sl;
Run Code Online (Sandbox Code Playgroud)
结果无法将类型转换System.Collections.Generic.List<string>为System.Collections.Generic.List<object>
当然,您可以通过从字符串列表中提取所有内容并将其一次放回一个来实现,但这是一个相当复杂的解决方案.
我有以下泛型类
public class Home<T> where T : Class
{
public string GetClassType
{
get{ return T.ToString() }
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我得到一个对象X,我肯定知道它是Home:
public void DoSomething(object x)
{
if(x is // Check if Home<>)
{
// I want to invoke GetClassType method of x
// but I don't know his generic type
x as Home<?> // What should I use here?
}
}
Run Code Online (Sandbox Code Playgroud)
我是否可以在不指定类的泛型类型的情况下进行转换?
以下为什么不工作?
List<string> castMe = new List<string>();
IEnumerable<string> getFromCast = (IEnumerable<string>)castMe; // allowed.
Dictionary<int, List<string>> castMeDict = new Dictionary<int, List<string>>();
Dictionary<int, IEnumerable<string>> getFromDict = (Dictionary<int, IEnumerable<string>>)castMeDict; // Not allowed
Run Code Online (Sandbox Code Playgroud)
这是Dictionary铸造机制中的一个缺陷,还是我认为应该允许这样做?
谢谢.
我有以下简短的C#程序:
IList<string> listString = new List<String>();
IList<object> listObject;
listObject = listString;
Run Code Online (Sandbox Code Playgroud)
这个程序不编译.最后一行导致以下编译错误:
无法将类型'System.Collections.Generic.IList'隐式转换为'System.Collections.Generic.IList'.存在显式转换(您是否错过了演员?)
所以,我添加了演员:
listObject = (IList<object>)listString;
Run Code Online (Sandbox Code Playgroud)
现在程序正确编译,但在运行时失败.的InvalidCastException升高与以下消息:
无法将类型为'System.Collections.Generic.List'1 [System.String]'的对象强制转换为'System.Collections.Generic.IList'1 [System.Object]'.
强制转换是非法的,应该被编译器捕获,或者它是合法的,不应该在运行时抛出异常.为什么行为不一致?
澄清:我不是在问为什么演员会失败.我明白为什么这样的铸造有问题.我问为什么演员阵容只在运行时失败.
在IMyMessage.cs中
public interface IMyMessage
{
}
Run Code Online (Sandbox Code Playgroud)
在IMyMessageReceiver.cs中
public interface IMyMessageReceiver<T> where T: IMyMessage
{
void HandleMessage(T message);
void Subscribe();
}
Run Code Online (Sandbox Code Playgroud)
在MyMessagePublisher.cs中
public static class MyMessagePublisher
{
private static Dictionary<Type, List<IMyMessageReceiver<IMyMessage>>> _subscribers;
static MyMessagePublisher
{
_subscribers = new Dictionary<Type, List<IMyMessageReceiver<IMyMessage>>>();
}
public static function Subscribe<T>(IMyMessageReceiver<T> receiver) where T: IMyMessage
{
Type messageType = typeof (T);
List<IMyMessageReceiver<IMyMessage>> listeners;
if(!_subscribers.TryGetValue(messageType, out listeners))
{
// no list found, so create it
List<IMyMessageReceiver<T>> newListeners = new List<IMyMessageReceiver<T>>();
// ERROR HERE: Can't convert List<IMyMessageReceiver<T>> to List<IMyMessageReceiver<IMyMessage>> …Run Code Online (Sandbox Code Playgroud) 这可能是重复的。但经过一天的研究,我希望得到你的宽大处理。这是一个关于协方差的问题。
为什么我可以做到这一点?
List<Animal> allAnimals = new List<Animal>();
allAnimals.Add(new Dog());
allAnimals.Add(new Cat());
Run Code Online (Sandbox Code Playgroud)
但不能这样做吗?
List<Dog> aBunchOfDogs = new List<Dog>();
allAnimals = aBunchOfDogs;
Run Code Online (Sandbox Code Playgroud)
我读过一些关于协方差的讨论。
我的理解是,我不能将狗列表添加到动物列表中,因为这样我可以将猫添加到动物列表中,这将是危险的。但是将猫或狗的单个实例添加到动物列表中也同样危险,不是吗?在我看来,C# 还没有决定是否信任我。
c# ×7
generics ×5
casting ×4
covariance ×4
.net ×2
c#-4.0 ×1
dictionary ×1
list ×1
type-safety ×1
types ×1