Generic method: cannot convert 'T' to ...

C

Christophe

class A {}

class B {}

interface MyInterface
{
void method(A a);
void method(B b);
}

class Foo
{
public Foo(MyInterface myInterface)
{
_myInterface = myInterface;
}

private bool Process<T>(T t)
{
if (t == null) return false;
_myInterface.method(t);

// The previous line generates 2 errors
// Error 1: The best overload method match for 'MyInterface.method(A)'
// has some invalid argument
// Error 2: cannot convert from 'T' to 'A'

return true;
}

// I would like to avoid to implement the core of Process
// for each type as follows:
// private bool Process(A a)
// {
// if (a == null) return false;
// _myInterface.method(a);
// return true;
// }
// private bool Process(B b)
// {
// if (b == null) return false;
// _myInterface.method(a);
// return true;
// }

public void Process(object o)
{
if (Process(o as A)) return;
if (Process(o as B)) return;
throw new Exception();
}

private MyInterface _myInterface;
}

I would like to avoid to implement Process for each type. How can I do
this in C# ?

Thanx.
 
S

Stoitcho Goutsev \(100\)

Christophe,

It is not possible to pull this off with generics.

The reason why you get this error message is that the compiler doesn't know
at the time of compilation what the real type of the object is.
In your case because it doesn't know the type of the object the compiler
cannot verify that the parameter can be converted to A type in order to call
the method. This can be overcome using constraints.
Unfortunately there might be only one type constriant, but we need to have
two in our case. You can rework the sample a little bit by marking the
classes with marker interfaces. The reason for doing this is because we may
have more than one interface constraint

interface IA{}
class A:IA { }

interface IB{}
class B:IB { }

interface MyInterface
{
void method(IA a);
void method(IB b);
}

class Foo
{
MyInterface _myInterface;
public Foo(MyInterface myInterface)
{
_myInterface = myInterface;
}

private bool Process<T>(T t) where T:IA,IB
{
if (t == null) return false;
_myInterface.method(t);

// The previous line generates 2 errors
// Error 1: The best overload method match for 'MyInterface.method(A)'
// has some invalid argument
// Error 2: cannot convert from 'T' to 'A'

return true;
}


}


Now if you try to compile this code you'll get antoher error, which I
believe is more easier to understand:
Error 2 The call is ambiguous between the following methods or properties:
'ConsoleApplication1.Program.MyInterface.method(ConsoleApplication1.Program.IA)'
and
'ConsoleApplication1.Program.MyInterface.method(ConsoleApplication1.Program.IB)'
D:\Projects\Delme2005\WindowsApplication1\ConsoleApplication1\Program.cs 50
5 ConsoleApplication1

And this is why you scenario cannot be implemented. The compiler doesn't
know the real type of the paramter, but it knows that it implements certain
interfaces, now when it comes to calling the methods it cannot decide which
one to call, both are possible. This sample by the way is not correct again
because neither B nor A implemets both interfaces, but it demonstrates what
error you'll eventually get.

Once again:
1. Without using constraints the effective base class for *t* is Object and
there is no conversion from Object to neither A or B.
2. There is no constraints that could help you in this case.
3. Even if there were such constraints the compiler eventually will stumble
with choosing the correct method overload to call.


These are my two cents. I hope other guys in the group will throw their
opinions on the problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top