tags:

views:

76

answers:

6

I have the following c# classes:

class A : Object
{
   foo() {}
}

class B : Object
{
   foo() {}
}

I want to write a generic method that applies to both:

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

this does not compile complaining the foo() is not a member of T. I can add a constraint for T to derive from one of the classes:

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

but how can I have it for both?

A: 

Define an interface that contains the foo method, and have classes A & B implement that interface. Then define an interface constraint on your generic type.

pmarflee
+5  A: 

Simply put you can't. There are a couple of approaches to work around this problem though.

The most common is to use an interface. Say IMyType

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

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

This is a bit heavy weight though is it requires a metadata change for a solution. A cheaper approach is to provide a lambda expression which calls the appropriate function.

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

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

You can't do that unless you:

  1. Derive from a base class
  2. Derive from an interface

I prefer the interface because it doesn't force you to share behavior:

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
}
Michael Meadows
+1  A: 

You should define an interface:

interface IFoo
{
   void foo();
}


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

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

And your generic method:

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

This is possible in .NET 4.0 using dynamic.

void bar(dynamic t)
{
  t.foo();
}
John Buchanan
A: 

Why are you making this generic? Just overload the method.

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

Generics are there so that you can make potentially infinite bar() methods.

Robert Davis