在Contravariance中,颠倒引用的分配兼容性意味着什么?
协方差和协方差(C#)
// Assignment compatibility.
string str = "test";
// An object of a more derived type is assigned to an object of a less derived type.
object obj = str;
// Covariance.
IEnumerable<string> strings = new List<string>();
// An object that is instantiated with a more derived type argument
// is assigned to an object instantiated with a less derived type argument.
// Assignment compatibility is preserved.
IEnumerable<object> objects = strings;
// Contravariance.
// Assume that the following method is in the class:
// static void SetObject(object o) { }
Action<object> actObject = SetObject;
// An object that is instantiated with a less derived type argument
// is assigned to an object instantiated with a more derived type argument.
// Assignment compatibility is reversed.
Action<string> actString = actObject;
参考:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariance/
此外,当尝试从较少派生的类型转换为较高派生的类型时,会抛出InvalidCastException
。由于不允许用户定义的转换到基类或从基类进行用户定义的转换,因此我看不到方法组的矛盾性如何工作-是否/也不应该调用这样的方法抛出InvalidCastException
吗?
更新:https://blogs.msdn.microsoft.com/ericlippert/2009/11/30/whats-the-difference-between-covariance-and-assignment-compatibility/
参考方案
分配兼容性相反,这意味着您可以将派生次数较少的类型分配给派生程度较高的类型。
在示例中,逆差用Action
类显示。可以将Action<object>
分配给Action<string>
。
此代码有效:
public void Test(object o)
{
Console.WriteLine(o.GetType().ToString());
}
Action<string> foo;
foo = Test;
foo.Invoke("bar");
在此示例中,我们可以看到字符串“ bar”在作为参数传递给Test
方法时隐式转换为对象类型。没有无效的转换或用户定义的转换。
Action
不是协变的,因此无法将Action<string>
分配给Action<object>
,尝试这样做会引发异常。
当通用类型是输入参数并且与输出参数协变时,通用类型是互变的。
因此,Func
类与它的第一个类型协变而与它的第二个(和第三个……)相反。
可以将Func<string, object>
分配给Func<string, string>
可以将Func<string, string>
分配给Func<object, string>
可以将Func<string, object>
分配给Func<object, string>
Func<object, string>
不能分配给Func<string, string>
。
要在C#中声明一个逆向泛型类型,我们可以使用in
关键字声明一个逆向接口。为此,我们被限制使用泛型类型作为输入参数:
interface IMyGenericType<in T>
{
object Test(T input); //allowed
//T GetValue(); //not allowed in a contravariant interface
}
通过这种类型,我可以将IMyGenericType<object>
分配给IMyGenericType<string>
。
我看过类似的问题,但没有什么合适的。我有一个碰巧包含列表的对象。我想把它变成我可以列举的东西。例如:object listObject; // contains a List<Something> List<object> list; list = listObject as List<object>; // list c…
为什么要使用Func <string>而不是string? - c#为什么要使用Func<string>而不是string?我的问题特别是关于this回购。有问题的行是22: private static Func<string> getToken = () => Environment.GetEnvironmentVariable("GitHubToken", Enviro…
无法从ArrayList <String>转换为List <Comparable> - java当我写下面的代码时,编译器说 无法从ArrayList<String>转换为List<Comparable>private List<Comparable> get(){ return new ArrayList<String>(); } 但是当我用通配符编写返回类型时,代码会编译。private List&l…
将谓词<T>转换为Func <T,bool> - c#我有一个包含成员Predicate的类,希望在Linq表达式中使用该类:using System.Linq; class MyClass { public bool DoAllHaveSomeProperty() { return m_instrumentList.All(m_filterExpression); } private IEnumerable&…
C#协方差混淆 - c#以下是有关C#中协方差的代码段。我对如何应用协方差有一定的了解,但是我很难掌握一些详细的技术知识。using System; namespace CovarianceExample { interface IExtract<out T> { T Extract(); } class SampleClass<T> : IExtract&…