如何确定方法返回哪个接口

5

给定以下代码片段,可以轻松粘贴到Linqpad中(或在Visual Studio控制台解决方案中进行轻微修改):

void Main()
{
    var cat = this.GetCat();
    var dog = this.GetDog();
    cat.Think();
    cat.ThinkHarder();
    //dog.Think(); // Does not compile.
    //dog.ThinkHarder(); // Does not compile.

    //if ([dog is returned as ISmartAnimal]) // What to put here?
        ((ISmartAnimal)dog).Think(); // Compiles, runs, but shouldn't.

    reportTypeProperties(cat);
    reportTypeProperties(dog);
}

interface IAnimal
{
    string Name { get; set; }
}

interface ISmartAnimal : IAnimal
{
    void Think();
}

class Animal : IAnimal, ISmartAnimal
{
    public string Name { get; set; }
    public void Think() { }
}

ISmartAnimal GetCat()
{
    return new Animal();
}

IAnimal GetDog()
{
    return new Animal();
}

static void reportTypeProperties(object obj)
{
    var type = obj.GetType();
    Console.WriteLine("Type: {0}", type.Name);
    Console.WriteLine("Is smart? {0}", obj is ISmartAnimal);
}

static class ext
{
    public static void ThinkHarder(this ISmartAnimal animal)
    { }
}
reportTypeProperties的输出结果表明,虽然dog被返回为IAnimal,但它实际上是一个ISmartAnimal。(两个对象都是如此)

类型:动物
智能?True

这是因为GetType()返回的是对象的具体类型,而不是它当前的接口。
我的问题是:有没有办法告诉我们dog是否以IAnimal的形式返回?(见伪代码)。编译器知道(快速视图也知道)。假设我有一些动物对象,并且我想在运行时代码中检查是否可以让它Think()
背景:
这可能看起来像一种学术性质的练习。并且看起来很奇怪,因为Animal类实现了一个你不想总是暴露的接口(ISmartAnimal)。但我之所以问是因为我在Entity Framework中遇到了类似的情况。如果您想了解更多信息,请单击此处,但它会转向EF特定的功能。如果您不想深入研究,那么Animal同时实现这两个接口是至关重要的。
免责声明:
“任何与真实动物的相似之处纯属巧合 :)”
1个回答

5

听起来您对dog变量的编译时类型很感兴趣。您可以通过使ReportTypeProperties具有泛型,并让编译器根据变量类型推断类型来获取一定程度的结果:

static void ReportTypeProperties<T>(T obj)
{
    Console.WriteLine("Compile-time type: {0}", typeof(T).Name);
    Console.WriteLine("Actual type: {0}", obj.GetType().Name);
    Console.WriteLine("Is smart? {0}", obj is ISmartAnimal);
}

请注意,这个可以用各种方式来操控,例如:
object dog = GetDog();
ReportTypeProperties(dog); // Would show as object

或者

IAnimal dog = GetDog();
ReportTypeProperties<object>(dog); // Would show as object

这里的整体思路不是很清晰 - 我觉得朝这个方向发展不太可能会导致一个好的设计。


谢谢(再次)Jon。这不是我想经常实现的设计,但我对EF的ObjectQuery(以及linq-to-sql中的DataQuery)使用IQueryable和IOrderedQueryable做同样的事情感到有些惊讶。虽然我相信这样做有很好的理由。 - Gert Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接