在子类中使用非泛型方法“隐藏”泛型方法

时间:2015-03-31 18:05:16

标签: c# generics method-overriding

我已经编写了一些代码,我很好奇我所做的事情是否存在我不知道的危险。

我试过搜索,我发现的大多数问题都是关于如何制作通用的问题,这不是我的问题。我还查看了.net 4.5的C#规范,第13.4.3节 - 通用方法和7.5.2关于类型推断,最后是7.5.2.12推断的返回类型,它们并没有真正涵盖我所做的事情。我试图做。

基本上我有一个类的层次结构

public class SomeBaseClass { }
public class SomeClass : SomeBaseClass { }
public class AnotherClass : SomeBaseClass { }

public class BaseData
{
    public SomeBaseClass mMember;
    public BaseData() { }
    public TType GetMember<TType>()
        where TType : SomeBaseClass
    {
        return (TType)mMember;
    }
}

public class Data : BaseData
{
    public Data()
    {
        mMember = new SomeClass();
    }

    //Is this bad
    public SomeClass GetMember()
    {
        return base.GetMember<SomeClass>();
    }
}

编译器没有抱怨,因为我没有隐藏基类方法。这表明intellisense将它们列为两个单独的方法。我已经编写了几个测试,这些测试都按照我期望的方式进行,并且在查看List&lt;&gt;之类的内容时。有一些方法同时具有泛型和非泛型实现(例如来自ParallelEnumerable的AsParallel)但不同之处在于,在这种情况下,两个方法都存在于同一个类中,并分别接受泛型和非泛型参数。

我运行的测试和按照我预期的方式显示的工作如下所示。

class Program
{
    static void Main(string[] args)
    {
        BaseData lData = new Data();
        Data lData2 = new Data();

        //Call base method with type
        SomeBaseClass lTest = lData.GetMember<SomeClass>();

        //Cast and call derived method
        SomeClass lTest2 = ((Data)lData).GetMember();

        //Call base method with type and then cast
        SomeClass lTest3 = (SomeClass)lData.GetMember<SomeBaseClass>();

        //Call derived method directly
        SomeClass lTest4 = lData2.GetMember();

        //Throw InvalidCastException
        SomeBaseClass lTest5 = lData2.GetMember<AnotherClass>();
    }
}

这样做的主要原因是,当类本身已经拥有此信息时,我希望任何调用者代码都不必知道泛型类型。这是为了避免写

lData.GetMemberType<...>();

到处都是。

如果这个问题过于宽泛或存在主张,我道歉。大多数情况下,我只是想知道这个场景中是否有任何东西不会像我想象的那样工作或有隐藏的bug等。

1 个答案:

答案 0 :(得分:1)

你的问题有点过于含糊,无法给出一个非常好的答案(你用的是什么?这个设计的目的是什么?)。

我认为名称重叠并不是问题所在,但它看起来似乎是一个有问题的设计和滥用泛型的症状(所有这些都应该让你知道这一点)。

理想情况下,您的类本身应该是通用的,您应该始终使用泛型类型参数。这将使你免于正在进行的所有演员阵容:

public class SomeBaseClass { }
public class SomeClass : SomeBaseClass { }
public class AnotherClass : SomeBaseClass { }

public class BaseData<TType> where TType : SomeBaseClass
{
    protected TType mMember;
    public BaseData() { }
    public BaseData(TType member)
        : this()
    {
        mMember = member;
    }

    public TType GetMember()
    {
        return mMember;
    }
}

public class Data : BaseData<SomeClass>
{
    public Data()
        : base(new SomeClass())
    {
    }

    // no need to implement GetMember(); base class has it covered
}