Учитывая этот фрагмент кода, который может быть легко вставлен в 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. Если вы хотите, вы можете прочитать об этом here, но он отвлекается на функции EF. Если вы не хотите вникать в это, достаточно сказать, что необходимо, чтобы Animal
реализовали оба интерфейса.
Отказ от ответственности:
«Любое сходство с реальными животными чисто случайно :)»
Спасибо (еще раз) Джон. Это не дизайн, который я хотел бы реализовать слишком часто, но я был немного удивлен тем, что ObjectQuery (и DataQuery от EF в linq-to-sql) EF выполняет то же самое с IQueryable и IOrderedQueryable. Хотя я уверен, что есть веские причины для этого. –