在Contravariance中,颠倒引用的分配兼容性意味着什么? - c#

在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>

将对象转换为List <object> - c#

我看过类似的问题,但没有什么合适的。我有一个碰巧包含列表的对象。我想把它变成我可以列举的东西。例如: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&…