2011-04-08 93 views
1

我一直在与此争斗一段时间,所以任何帮助将不胜感激。这是我在C#.NET 4.0中遇到的场景。C#.NET 4.0抛出异常的泛型协方差问题

public interface ITableBusinessLogicLayerIn<in TTableRecord> : IBusinessLogicLayer 
    where TTableRecord : ITableRecord 
{ 
// No definition 
} 

public interface ITableBusinessLogicLayerOut<out TTableRecord> : IBusinessLogicLayer 
    where TTableRecord : ITableRecord 
{ 
// No definition 
} 

我有一个对象,它实现了两个接口。代码编译正常。但在运行时,我能够施放此对象如下:

(ITableBusinessLogicLayerOut<ITableRecord>)obj 

但不是这样的:

(ITableBusinessLogicLayerIn<ITableRecord>)obj 

这是非常令人困惑,我不知道我在做什么错。有人请给我指出正确的方向。谢谢!

+0

我确定这与“in”泛型参数主要用于lambdas和方法而不用于类的事实有关,因为它们都是关于传递值“in”的。虽然这是我的一切。 :) – 2011-04-08 05:08:47

回答

3

逆变(in)允许您将具有较少特定类型的类型参数的对象转换为更具体的类型之一。例如,不能将对象传递给期望字符串的类型,因此您不能将需要字符串的类型转换为期望对象的类型。在这里看到更多的信息:http://msdn.microsoft.com/en-us/library/ee207183%28d=lightweight%29.aspx

考虑下面的例子:

class MyTableRecord : ITableRecord { } 
ITableBusinessLogicLayerIn<ITableRecord> inA; 
ITableBusinessLogicLayerIn<MyTableRecord> inB; 
ITableBusinessLogicLayerOut<ITableRecord> outA; 
ITableBusinessLogicLayerOut<MyTableRecord> outB; 

您可以分配到inBinA,而不是相反。您可以将outA指定为outB,但不能相反。

+0

嗨Talljoe。我需要使用通用接口ITableBusinessLogicLayerIn,以便我可以添加,更新任何类型的ITableRecord对象,即UserRecord,RoleRecord,MenuRecord等。我将如何实现这一目标? – c0D3l0g1c 2011-04-08 05:21:47

+0

对于你在做什么你可能不需要差异。一个简单的通用将起作用。只有当您希望能够将一种类型用于另一种类型的情况时,方差才是可能的,因为这两种类型都是相同的通用基础,但具有不同的类型参数(如在某些需要IEnumerable 的地方使用IEnumerable )。你通常必须选择一个方向或另一个方向,你不能同时做(或者你基本上以不变为结果)。 – Talljoe 2011-04-08 05:39:20

+0

感谢您的回答和建议。非常感激。 – c0D3l0g1c 2011-04-08 05:44:10