在从非泛型接口继承的泛型类型中实现泛型方法时出现问题

时间:2011-06-02 18:27:05

标签: c# .net generics

我有一个带有两个通用方法签名的非泛型接口。

interface IDataContainer
{
    T GetValue<T>();
    void SetValue<T>(T value);
}

然后我有一个实现IDataContainer

的泛型类
public class DataContainer<T>: IDataContainer
{
    private T _value;

    #region IDataContainer Members

    public T GetValue<T>()
    {
        return _value;
    }

    public void SetValue<T>(T value)
    {
        _value = value;
    }

    #endregion
}

我收到的错误是无法在已实现的GetValue和SetValue方法上将类型T隐式转换为T.

有没有办法解决这个问题?平等的某种类型约束?还有更好的方法吗?

我知道我可以通过使它成为IDataContainer<T>来使IDataContainer变得通用,但是当T不总是相同的类型时,我就没有IDataContainer的列表。

3 个答案:

答案 0 :(得分:1)

您的问题是编译器看到两种不同的类型。 IDataContainer范围内的T与泛型方法范围内的T不同,因此编译器会抱怨。

因为您的容器包含T的实例,我认为您的接口也应该具有类型参数T(不仅仅是方法范围泛型参数)。

您当前的界面实际承诺(记住,界面是合约),能够为任何T提供T值 - 肯定不是您想要的?

答案 1 :(得分:1)

您可以在通用界面中很好地捕获代码的意图:

interface IDataContainer<T> {
  T GetValue();
  void SetValue(T value);
}

那你为什么要使用泛型方法的非通用接口?

泛型方法的问题是类型参数不是相同的,尽管它们具有相同的名称。

要获得T不相同时的数据容器列表,只需为通用接口设置非通用的基本接口:

interface IDataContainer { }

interface IDataContainer<T> : IDataContainer { 
  ...
}

然后您可以拥有非通用数据容器的列表。

答案 2 :(得分:0)

这两种方法意味着两种不同的东西。在IDataContainer中,指定泛型方法。这可以用任何类型调用。在DataContainer中,指定采用类中指定的特定类型参数的方法。 IDataContainer不满足DataContainer的合同。您应该更改IDataContainer,以便它是通用的。

为了更清楚,请单独考虑IDataContainer。无论getContainer()

返回的具体容器如何,以下代码都应合法
IDataContainer ctr = getContainer();
String x = ctr.getValue<String>();

但是,如果getContainer看起来如下所示,那么如果您拥有的内容合法,那么该代码会明显破解:

public IDataContainer getContainer() {
    return new DataContainer<Foo>();
}

您遇到的根本问题是,如果您有不同类型的DataContainer,那么这些DataContainer的合同就完全不同了。 DataContainer<Foo>有一个GetValue可以为您提供Foo,而DataContainer<Bar>有一个GetValue会为您提供Bar。如果有一个Foo和Bar的超类,那么你可以使用它,否则,你将要进行投射,因为如果你把它们一起扔进一个列表中就不能保证类型安全。