2012-06-05 3 views
2

У меня есть сценарий, в котором есть два класса, которые говорят ClassA и ClassB с методами MethodA и MethodB соответственно. Я должен написать обобщенный метод, который возвращает экземпляры объектов вышеуказанных классов в зависимости от условия некоторой целочисленной переменной say x. Когда я пытаюсь код ниже, я получаю сообщение об ошибке: «Не удается неявно преобразовать CLASSA Т» или «Не удается неявно преобразовать ClassB Т»Возвращает объект одного класса в общий метод

public ClassA 
{ 
    public void MethodA() 
    { 
     //method implementation 
    } 
} 

public ClassB 
{ 
    public void MethodB() 
    { 
     //method implementation 
    } 
} 

Общий метод, как

public T MethodGeneric<T>() 
{ 
    int x; 
    ClassA objectA = new ClassA(); 
    ClassB objectB = new ClassB(); 

    if(x==2) 
    { 
     return objectA; 
    } 
    else 
    { 
     return objectB; 
    } 
} 
+1

Дайте классу A и B базовый класс или интерфейс commom и ограничите T этим типом. – asawyer

+0

- или просто бросить: "return (T) objectA;" и т.п. –

+1

@ 500-InternalServerError Затем, когда кто-то говорит 'MethodGeneric ', они возвращают ваш тезка обратно в ответ. – asawyer

ответ

4

Проблема заключается в том что T не является ClassA или ClassB.

Вы могли бы попытаться справиться с этим с помощью литья, например, так:

public static T MethodGeneric<T>() where T : class 
{ 
    int x = 2; 
    ClassA objectA = new ClassA(); 
    ClassB objectB = new ClassB(); 

    if (x == 2) 
    { 
     return objectA as T; 
    } 
    else 
    { 
     return objectB as T; 
    } 
} 

Однако, это не защитит вас, если кто-то звонит MethodGeneric<ClassC>(), кроме возвращения null в этом случае.

Вы можете сделать это более безопасным, если у вас есть ClassA и ClassB оба происходят из того же базового класса или интерфейса, что и тогда можно было бы установить общее ограничение, которое уменьшило бы вероятность ошибки. Однако это все равно не было бы абсолютно безопасным способом работы, поскольку дженерики не были бы уместными. Это может быть лучше иметь интерфейс, реализованный обоих классов (то есть: IClassBase), а затем не использовать дженерики, но вернуть интерфейс:

public IClassBase CreateInstance() 
{ 
    //... 
     return objectA; // This will work fine, provided ClassA implements IClassBase 
} 
+2

Я не думаю, что вы можете использовать этот способ 'return (T) objectA' в любом случае. Вам нужно нажать на объект сначала «return (T) (object) objectA;», но я согласен с остальными. – Marc

+0

Если он хочет иметь возможность вызывать типы конкретных методов по имени в исходных типах, это все напрасно. Нужен еще один слой абстракции. – asawyer

+0

@asawyer Да - это довольно бессмысленно, если не существует определенного контракта на месте - как интерфейс, который можно использовать. –

0

от вашего this double-post, который закрыт, вы близки. Вы передаете object в качестве аргумента типа, который вернет снова тот же T, который является object в вашем случае. Вот почему вы не можете использовать свойства, определенные на объектах ClassA. Вместо этого вы должны пройти требуемый тип, например ClassB или ClassC. Может быть, это:

public T getObject<T>(int i) where T : ClassA 
{ 
    if(i == 1) 
    { 
     ClassB objB = new ClassB(); 
     return objB as T; 
    } 
    else 
    { 
     ClassC objC = new ClassC(); 
     return objC as T; 
    } 
} 

public static void main() 
{ 
    var obj = getObject<ClassB>(5); //which wont work anyway since i == 5 !! 
    obj.aValue = 20; 
    obj.bValue = 30; 
    //obj.cValue = 40; this wont work since obj is of type ClassB 

    //or 

    var obj = getObject<ClassC>(5); 
    obj.aValue = 20; 
    //obj.bValue = 30; this wont work since obj is of type ClassC now 
    obj.cValue = 40; 
} 

Я не уверен, почему вы проверяете переменную int i решить, что тот тип, который должен быть возвращен. Это не настоящее использование дженериков. Подлинное использование дженериков может выглядеть следующим образом:

public T getObject<T>(int i) where T : ClassA 
{ 
    return new T(); //without the use of int i 
} 

Если int i является то, что решает, какой объект должен быть возвращен обратно, то почему бы использовать дженерики вообще? Вы можете очень хорошо сделать:

public ClassA getObject(int i) 
{ 
    if(i == 1) 
    { 
     ClassB objB = new ClassB(); 
     return objB; 
    } 
    else 
    { 
     ClassC objC = new ClassC(); 
     return objC; 
    } 
} 

public static void main() 
{ 
    var obj = getObject(5); 
    if (obj is ClassB) 
    { 
     obj.aValue = 20; 
     obj.bValue = 30; 
     //obj.cValue = 40; this wont work since obj is of type ClassB 
    } 
    //or 

    var obj = getObject(5); 
    if (obj is ClassC) 
    { 
     obj.aValue = 20; 
     //obj.bValue = 30; this wont work since obj is of type ClassC 
     obj.cValue = 40; 
    } 
} 

но улов вы должны проверить тип от вызывающей стороны (Main).

И если вы хотите назначить свойства bValue и cValue на обоих ClassB и ClassC объектов, то вы должны написать эти свойства в ClassA.

Кроме того, вы используете только get аксессуар, вам необходимо указать set.

Смежные вопросы