2013-07-12 54 views
1

我有几个地方我都使用Action<Int32>Action<Boolean>Action<SomeClassName>,但是当涉及到传递行动的一类方法的参数,我不能投Action<Int32>Action<Boolean>Action<Object>为什么我不能动作<Int32>动作<Object>?

为什么不能用简单的类型转换进行转换?这个演员是可能的吗?最后,如果可能的话,我将如何去做这个演员阵容。

回答

10

因为它会破坏类型安全。

当您声明Action<Int32>时,您说“这是需要一个Int32参数的代表”。

如果这可以直接转换为Action<object>,那么您现在可以使用肯定不是Int32的行为来调用动作,例如DateTime。在这种情况下,C#可以防止你在脚下拍摄自己。

3

你不能让经协方差直接投(或者是逆变?),因为Action<int>根本不一个Action<object> - 后者可以传递任何对象,而前者可以只通过了int

可以围绕此包裹你的动作,这样的:

Action<int> aInt = ...; 
Action<object> aObj = o => aInt((int)o); 

这再次表明你为什么投可能不是一个好主意 - 如果你通过aObj任何东西,除了一个int,你会得到一个演员例外。

相反,你可以理论上只投一个Action<object>Action<int>,因为如果你可以通过它任何对象,可以肯定它的int。但是,实际上这只适用于参考类型,而不适用于值类型 - 因此您可以使用string,但不适用于int

+1

这将是协变性,但'行动'在T中是逆变的。它是协变性,如果“可转换性箭头”朝相同的方向。如果'string - > object'暗示'X - > X '那么'X '是协变的,因为箭头相互对应。如果'string - > object'意味着'X <-- X'那么箭头是相反的方向,所以它是逆变的。 –

+0

...就这样,'co'和'contra'现在对我有意义。谢谢埃里克! – Rawling

1

在输入为Int32的限制下进行操作。这意味着您使用的操作可以对输入作为int进行假设。例如,你可以用另一个int n => Console.WriteLine(n + 4)做数学运算。所以这个动作或功能很适合那个盒子。如果你改变方框,以前做出的假设仍然必须保持。你基本上有一个反向关系,或逆变,到“常规”铸造方案,例如:object a = (object) 2;

只要记住任何符合操作框的东西都不会对其输入行为做任何假设。功能n => Console.WriteLine(n)紧贴在里面,因为所有的对象都可以被打印。并非所有对象都可以像整数一样操作。

相关问题