2010-03-18 2 views
2

I имеют следующие C# классы:Generics: Как получить один из двух классов?

class A : Object 
{ 
    foo() {} 
} 

class B : Object 
{ 
    foo() {} 
} 

Я хочу написать общий метод, который применяется к обоим:

void bar<T>(T t) 
{ 
    t.foo(); 
} 

это не компилируется жалуется на Foo() не является членом T Я могу добавить ограничение для того, чтобы Т получался от одного из классов:

void bar<T>(T t) where T : A 

но как я могу его использовать для обоих?

+0

Отвлекитесь немного от вопроса. Если это прецедент, имеет ли смысл иметь общий метод? Почему бы просто не реализовать интерфейс «IFoo» как для A, так и для B и объявить метод как void bar (IFoo f) { f.foo(); } – Biswanath

ответ

5

Проще говоря, вы не можете. Однако есть несколько подходов к решению этой проблемы.

Наиболее распространенным является использование интерфейса. Скажем IMyType

interface IMyType { void foo(); } 
class A : IMyType ... 
class B : IMyType ... 

void bar<T>(T t) where T : IMyType { 
    t.Foo(); 
} 

Это тяжелый вес немного, хотя это требует изменения метаданных для решения. Более дешевый подход заключается в предоставлении лямбда-выражения, которое вызывает соответствующую функцию.

void bar<T>(T t, Action doFoo) { 
    ... 
    doFoo(); 
} 

var v1 = new A(); 
var v2 = new B(); 
bar(v1,() => v1.Foo()); 
bar(v2,() => v2.Foo()); 
1

Определить интерфейс, содержащий метод foo, и иметь классы A & B реализовать этот интерфейс. Затем определите ограничение интерфейса для вашего общего типа.

1

Вы не можете сделать, если вы:

  1. Выведите из базового класса
  2. проистекают из интерфейса

Я предпочитаю интерфейс, потому что он не форсирует вы должны делиться поведением:

public interface IHasFoo 
{ 
    void foo(); 
} 

public class B : IHasFoo // you don't need to explicitly subclass object 
{ 
    public void foo() 
    { 
    } 
} 

public class A : IHasFoo // you don't need to explicitly subclass object 
{ 
    public void foo() 
    { 
    } 
} 

void bar<T>(T t) where T : IHasFoo 
{ 
    t.foo(); // works 
} 
2

Вы должны определить интерфейс:

interface IFoo 
{ 
    void foo(); 
} 


class A : IFoo 
{ 
    public void foo() {} 
} 

class B : IFoo 
{ 
    public void foo() {} 
} 

И ваш общий метод:

void bar<T>(T t) where T:IFoo 
{ 
    t.foo(); 
} 
1

Это возможно в .NET 4.0 с помощью dynamic.

void bar(dynamic t) 
{ 
    t.foo(); 
} 
0

Почему вы делаете это общее? Просто перегрузите метод.

void bar(A a) { a.Foo(); } 
void bar(B b) { b.Foo(); } 

Дженерики есть, так что вы можете сделать потенциально бесконечна bar() методы.

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