我试图理解实践中的逆转。当我读这本书时似乎很简单,但现在我似乎已经卡住了。 我知道有很多关于逆变的主题,我用Google搜索了很多,没有人帮助我理解这个特殊的问题 以下是Microsoft文档所说的https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance
这是我的代码:
using static System.Console;
namespace CSharpTests
{
class Program
{
delegate void Action<T> (T obj);
static void Main(string[] args)
{
Action<Device> b = DeviceAction;
Action<Mouse> d = b; // Error cannot implicitly convert type CSharpTests.Program.Action<CSharpTests.Device> to CSharpTests.Program.Action<CSharpTests.Mouse>
d(new Mouse());
ReadLine();
}
private static void DeviceAction(Device target) {
WriteLine(target.GetType().Name);
}
}
class Device { }
class Mouse : Device { }
}
关键区别是什么?我的代码甚至没有编译。正如你所看到的,我有一个代表接受泛型类型,据我所知,它允许相反的变换。但在实践中,我得到了一个编译时错误。 我也尝试使用“out”参数并获得相同的错误
using static System.Console;
namespace CSharpTests {
class Program {
delegate void Action<T> (out T obj);
static void Main(string[] args) {
Action<Device> b = DeviceAction;
Action<Mouse> d = b; // Error cannot implicitly convert type CSharpTests.Program.Action<CSharpTests.Device> to CSharpTests.Program.Action<CSharpTests.Mouse>
Mouse m;
d(out m);
ReadLine();
}
private static void DeviceAction(out Device target) {
target = new Device();
WriteLine(target.GetType().Name);
}
}
class Device { }
class Mouse : Device { }
}
答案 0 :(得分:3)
您要使用T
参数声明一个不变的out
:
delegate void Action<T> (out T obj);
将out
移至Action<out T>
会为您提供协变T
。你想要做的是这个(带有参数的逆变T
):
delegate void Action<in T> (T obj);
答案 1 :(得分:3)
将签名更改为delegate void Action<in T>(T arg)
。
将类型参数声明为in
表示违反; out
表示协方差。
您通常可以告诉使用哪一个,因为in
用于输入(例如,参数)而out
用于输出(例如,返回值)。
答案 2 :(得分:-1)
你创建一个target = new Device(); 这和你输入的内容不一样......
试试这样:
[TestClass]
public class Method_Tetsts
{
class Device { }
class Mouse : Device { }
[TestMethod]
public void ActionTest()
{
void DeviceAction<T>( T target)
{
Assert.AreEqual(target.GetType().Name, "Mouse");
}
Action<Device> b = DeviceAction;
Action<Mouse> d = b; // Error cannot implicitly convert type CSharpTests.Program.Action<CSharpTests.Device> to CSharpTests.Program.Action<CSharpTests.Mouse>
d(new Mouse());
}
}