我在微软的逆变示例中遗漏了什么?
What am I missing in Microsoft's contravariance example?
我正在尝试理解实践中的逆变。看书的时候好像很直白,现在好像卡住了。
我知道有很多关于逆变的话题,我用谷歌搜索了很多,none 帮助我理解了这个特殊问题
这是 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 { }
}
在这里你声明了一个不变量 T
和 out
参数:
delegate void Action<T> (out T obj);
将 out
移动到 Action<out T>
会给你一个 协变 T
。你想要做的是这个(一个带有参数的逆变 T
):
delegate void Action<in T> (T obj);
将签名更改为delegate void Action<in T>(T arg)
。
将类型参数声明为in
表示逆变; out
表示协方差。
您通常可以分辨出使用哪一个,因为 in
用于 输入 (例如,参数)而 out
用于 输出(例如,return 值)。
好吧,你创建了一个目标 = 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());
}
}
我正在尝试理解实践中的逆变。看书的时候好像很直白,现在好像卡住了。 我知道有很多关于逆变的话题,我用谷歌搜索了很多,none 帮助我理解了这个特殊问题 这是 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 { }
}
在这里你声明了一个不变量 T
和 out
参数:
delegate void Action<T> (out T obj);
将 out
移动到 Action<out T>
会给你一个 协变 T
。你想要做的是这个(一个带有参数的逆变 T
):
delegate void Action<in T> (T obj);
将签名更改为delegate void Action<in T>(T arg)
。
将类型参数声明为in
表示逆变; out
表示协方差。
您通常可以分辨出使用哪一个,因为 in
用于 输入 (例如,参数)而 out
用于 输出(例如,return 值)。
好吧,你创建了一个目标 = 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());
}
}