Mer*_*OWA 12 c# out covariance
我不清楚为什么下面的代码片段不是covarient?
public interface IResourceColl<out T> : IEnumerable<T> where T : IResource {
int Count { get; }
T this[int index] { get; }
bool TryGetValue( string SUID, out T obj ); // Error here?
}
Run Code Online (Sandbox Code Playgroud)
错误1无效方差:类型参数"T"必须在'IResourceColl.TryGetValue(string,out T)'上不变地有效.'T'是协变的.
我的界面仅在输出位置使用模板参数.我可以轻松地将此代码重构为类似的东西
public interface IResourceColl<out T> : IEnumerable<T> where T : class, IResource {
int Count { get; }
T this[int index] { get; }
T TryGetValue( string SUID ); // return null if not found
}
Run Code Online (Sandbox Code Playgroud)
但我试图了解我的原始代码是否真的违反了协方差,或者这是协方差的编译器还是.NET限制.
Bro*_*ass 13
问题确实在这里:
bool TryGetValue( string SUID, out T obj ); // Error here?
Run Code Online (Sandbox Code Playgroud)
您将obj标记为out参数,这仍然意味着您传入的内容 obj因此无法协变,因为您既传递了类型的实例又T返回了它.
编辑:
Eric Lippert说它比任何人都更好地提到他的答案"在C#中引用参数并且不能被标记为变体"并引用他关于out参数:
将T标记为"out"是否合法?很不幸的是,不行."out"实际上与幕后的"ref"没有什么不同."out"和"ref"之间的唯一区别是编译器禁止在被调用者分配之前从out参数读取,并且编译器在被调用者正常返回之前需要赋值.以C#以外的.NET语言编写此接口实现的人可以在初始化之前从该项读取,因此可以将其用作输入.因此,在这种情况下,我们禁止将T标记为"out".这是令人遗憾的,但我们无能为力; 我们必须遵守CLR的类型安全规则.