Reputation: 65
I have a scenario where there are two classes say ClassA and ClassB with methods MethodA and MethodB respectively. I have to write generic method that returns the object instances of the above classes depending on the condition of some integer variable say x. When I try the code below, I get an error that says "Cannot implicitly convert ClassA to T" or "Cannot implicitly convert ClassB to T"
public ClassA
{
public void MethodA()
{
//method implementation
}
}
public ClassB
{
public void MethodB()
{
//method implementation
}
}
Generic method as
public T MethodGeneric<T>()
{
int x;
ClassA objectA = new ClassA();
ClassB objectB = new ClassB();
if(x==2)
{
return objectA;
}
else
{
return objectB;
}
}
Upvotes: 2
Views: 328
Reputation: 73163
From your this double-post which is closed, you're close. You're passing object
as type argument, which will return again the same T
that is object
in your case. That's why you can't use the properties defined on ClassA
objects. Instead you should pass the required type like ClassB
or ClassC
. May be this:
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;
}
I'm not sure why you're checking variable int i
to decide what's the type that should be returned. That's not a true use of generics. A genuine use of generics might look like:
public T getObject<T>(int i) where T : ClassA
{
return new T(); //without the use of int i
}
If int i
is what decides which object to be returned back, then why use generics at all? You may very well do:
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;
}
}
but the catch is you have to check the type from caller side (Main).
And if you want to assign properties bValue
and cValue
on both ClassB
and ClassC
objects then you should write these properties in ClassA
.
Furthermore you're only using a get
accessor, you need set
as well to assign values.
Upvotes: 0
Reputation: 564333
The problem is that T
is not ClassA
nor ClassB
.
You could attempt to handle this via casting, like so:
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;
}
}
However, this will not protect you if somebody calls MethodGeneric<ClassC>()
, other than returning null
in that case.
You could make this safer if you have ClassA
and ClassB
both derive from the same base class or interface, as you could then put a generic constraint in place that would reduce the chance of error. However, this would still not be a completely safe way of working, as the generics wouldn't be appropriate. It might be better to have an interface implemented by both classes (ie: IClassBase
) and then not use generics, but return the interface:
public IClassBase CreateInstance()
{
//...
return objectA; // This will work fine, provided ClassA implements IClassBase
}
Upvotes: 4