如何将通过接口标识的对象强制转换为实现该接口的Generic类的特定对象

时间:2017-03-17 23:27:19

标签: c# generics casting

我有以下对象和类的设计。正如方法Play(Animal a)的评论中所述,我希望能够测试a实际上是Cat<Big>类型并相应地转换a以便我可以访问方法MethodUniqueToCats()

我可以通过Big获得a.GetType().GetGenericArguments()[0]。但是,不知何故,我没有实现如何从Animal转到Cat<Big>。我相信这是可能的,因为Visual Studio能够在运行时确定此信息(通过方法Play(Animal a)中的调试+断点检查)。

interface Animal
{
}

class Cat<T> : Animal
{
    public void MethodUniqueToCats()
    {
    }
}

class Dog<T> : Animal
{

}

class Freetime
{
    private Animal my_animal;

    public void Play(Animal a)
    {
        my_animal = a;
        Type t = a.GetType().GetGenericArguments()[0];
        // I would like to test if the type of 'a' passed to this 
        // method is a Cat and subsequently cast it to a Cat of type 't'
        // so that I can access 'MethodUniqueToCats()'.

        // Line below does not work but wondering how to go about:
        // if (a.GetType().IsAssignableFrom(typeof(Cat<t>))
        // How to do the 'casting'
    }
}

class MyProgram
{
    public static void Main(string[] args)
    {
        Freetime f = new Freetime();
        Cat<Big> c = new Cat<Big>();
        f.Play(c);
    }
}

提前致谢。

2 个答案:

答案 0 :(得分:0)

这个怎么样?

 if (a.GetGenericTypeDefinition() == typeof(Cat<>))
    {
       a.GetMethod("MethodUniqueToCats").Invoke(null, null)
    }

除非你绝对必须,否则我不会亲自去做。 我会在这里避免反思,即我会添加接口ICatIDog并尝试在你的方法中强制转换它。

答案 1 :(得分:0)

如果您绝对想这样做(并违反Liskov Substitution Principle),那么最简单的方法就是使用Cat的接口,如下所示:

interface IAnimal
{
}

interface ICat
{
    void MethodUniqueToCats();
}

class Cat<T> : IAnimal, ICat
{
    public void MethodUniqueToCats()
    {
    }
}

现在你可以测试你的对象是这样的猫:

IAnimal animal = new Cat<int>();

var cat = animal as ICat;
if (cat != null)
{
    cat.MethodUniqueToCats();
}

或者,如果您有幸运行C#v7(即Visual Studio 2017),您可以这样做:

if (animal is ICat cat)
{
    cat.MethodUniqueToCats();
}