Как определить, какой интерфейс возвращается методом

Учитывая этот фрагмент кода, который можно легко вставить в 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, "is" является ISmartAnimal. (Одинаково для обоих объектов)

  

Тип: Животное
  Умный? True

Это потому, что GetType() возвращает конкретный тип объекта, а не его текущий интерфейс.

Мой вопрос Есть ли способ сообщить, что dog возвращается как IAnimal? (см. псевдокод). Компилятор знает (так же, как и QuickView). Предположим, у меня был какой-то объект животного, и я хотел во время выполнения проверить, могу ли я сделать его Think().

Фон:
Это может показаться академическим упражнением. И может показаться странным, что класс (Animal) реализует интерфейс (ISmartAnimal), который вы не хотите показывать всегда. Но я спрашиваю, потому что я столкнулся с чем-то похожим в Entity Framework. Если вы хотите, вы можете прочитать об этом здесь , но он переходит на EF- специфические особенности Если вы не хотите вникать в это, достаточно сказать, что Animal необходимо реализовать оба интерфейса.


Отказ от ответственности:
«Любое сходство с реальными животными чисто случайно :)»

4 голоса | спросил Gert Arnold 30 Jpm1000000pmMon, 30 Jan 2012 15:29:02 +040012 2012, 15:29:02

1 ответ


0

Похоже, вы заинтересованы в типе времени компиляции переменной 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 Skeet 30 Jpm1000000pmMon, 30 Jan 2012 15:33:12 +040012 2012, 15:33:12

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132