2013-08-22 1 views
2

Предположив У меня есть метод:Cast T как имеющий интерфейс?

public void DoStuff<T>() where T : IMyInterface { 
... 
} 

и в других местах в другой метод, который я хочу, чтобы позвонить

public void OtherMethod<T>() where T : class { 
... 
if (typeof(T) is IMyInterface) // have ascertained that T is IMyInterface 
    DoStuff<T>(); 
} 

Есть ли какой-то способ, которым я могу бросить T как имеющий свой интерфейс?

DoStuff<(IMyInterface)T> и другие подобные варианты не будут работать для меня.

Редактировать: спасибо за указание на то, что typeof(T) is IMyInterface неправильный способ проверить интерфейс и должен вместо быть вызван фактическим экземпляром Т.

Edit2: Я обнаружил, что (IMyInterface).IsAssignableFrom(typeof(T)) работал в проверке для интерфейса.

+1

Не можете ли вы просто назвать это 'DuStuff '? – MarcinJuraszek

+0

И еще одна мысль: я думаю, что если вам нужен 'typeof (T)' внутри гена ric, возможно, вы не должны использовать дженерики вообще? – MarcinJuraszek

+1

@MarcinJuraszek Я не согласен. Иногда вы можете использовать 'typeof (T)' в общем методе. На самом деле, я бы сказал, что дженерики являются наиболее распространенным использованием оператора 'typeof'. –

ответ

3

Я думаю, что самый простой способ сделать это с отражением. Например.

public void OtherMethod<T>() where T : class { 
    if (typeof(IMyInterface).IsAssignableFrom(typeof(T))) { 
     MethodInfo method = this.GetType().GetMethod("DoStuff"); 
     MethodInfo generic = method.MakeGenericMethod(typeof(T)); 
     generic.Invoke(this, null); 
    } 
} 
+0

yeh Я надеялся, что смогу избежать этого, поскольку я уже создаю общие методы повсюду! Спасибо, хотя – DevDave

+0

@DevDave да, IMO показывает недостатки в поддержке дженериков C#, что нет лучшего способа сделать это. Вы не можете добавить ограничение после факта, вы не можете иметь два метода с теми же параметрами, но с ограничениями по типу или что-то еще, чтобы сделать это легко. –

1

Вы можете использовать тот же синтаксис, чтобы наследовать от нескольких интерфейсов:

public void OtherMethod<T>() where T : class, IMyInterface { 
... 
} 
+1

Возможно, это не вариант ('IMyInterface' может быть необязательным), но если вы это сделаете, это будет мой предпочтительный подход. –

+0

спасибо, да, я тоже это пробовал. И проблема в том, что он пузырится до вызывающего метода. Таким образом, T, переданный из OtherMethod, также должен быть T: class, IMyInterface, и это не всегда имеет место в моем коде – DevDave

1

Эта линия является неправильным:

if (typeof(T) is IMyInterface) // have ascertained that T is IMyInterface 
    DoStuff<T>(); 

typeof(T) возвращает Type, который будет никогда стать IMyinterface. Если у вас есть экземпляр Т, вы можете использовать

if (instanceOfT is IMyInterface) // have ascertained that T is IMyInterface 
    DoStuff<T>(); 

или

if (instanceOfT is IMyInterface) // have ascertained that T is IMyInterface 
    DoStuff<IMyInterface>(); 

В противном случае вы могли бы использовать отражение в Tim S suggests.

0

Ваш пример требует небольшой работы. То, что вы здесь делаете, во многом зависит от того, как вы используете IMyInterface внутри метода DoStuff.

Действительно ли ваш метод DoStuff «Т»? или просто нужно «IMyInterface»? В моем примере я передаю объект в «OtherMethod», определяя, реализует ли он IMyInterface », вызывая DoStuff и вызывая метод интерфейса для объекта.

Вы используете объекты вокруг: T»и„IMyInterface“в OtherMethod и DoStuff

Ваш метод DoStuff должны только родовое T:? IMyInterface, если это необходимо, чтобы иметь понимание как типа„ Т“и интерфейс„IMyInterface“

public void DoStuff(IMyInterface myObject) 
    { 
     myObject.InterfaceMethod(); 
    } 

    public void OtherMethod<T>(T myObject) 
     where T : class 
    { 
     if (myObject is IMyInterface) // have ascertained that T is IMyInterface 
     { 
      DoStuff((IMyInterface)myObject); 
     } 
    } 
Смежные вопросы