Reputation: 2942
Consider the following code;
class SomeType1
{
}
class SomeType2
{
}
class CombinedType
{
public static implicit operator CombinedType(SomeType1 source)
{
return new CombinedType
{
...
};
}
public static implicit operator CombinedType(SomeType2 source)
{
return new CombinedType
{
...
};
}
}
void SomeMethod()
{
var listOfType1 = new List<SomeType1>();
DoSomethingWith(listOfType1);
var listOfType2 = new List<SomeType2>();
DoSomethingWith(listOfType2);
}
void DoSomethingWith<T>(IEnumerable<T> stuff)
{
IEnumerable<CombinedType> converted = stuff.Select(i => (CombinedType) i);
...
}
This fails with
Error CS0030 Cannot convert type 'T' to 'CombinedType'
However, I know that an implicit conversion exists between T
and CombinedType
when T
is either SomeType1
or SomeType2
. How can I tell the compiler that this should be possible? I cannot add where T : CombinedType
on the generic method because that is not true.
Upvotes: 0
Views: 113
Reputation: 42245
Implicit conversions are just method calls which are inserted by the compiler at compile time.
For example:
CombinedType c = new SomeType1();
gets turned into:
CombinedType c = CombinedType.op_Implicit(new SomeType1());
The JIT doesn't have the knowledge to insert these method calls. Yet, generics are expanded at JIT-time, which is when you want this to happen.
Don't forget that your code also allows someone to pass in a T
which isn't convertible to a CombinedType
.
You've got a few options, however.
One is:
void DoSomethingWith<T>(IEnumerable<T> stuff)
{
IEnumerable<CombinedType> converted = stuff.Select(i => i switch
{
SomeType1 s1 => (CombinedType)s1,
SomeType2 s2 => (CombinedType)s2,
_ => throw ...
});
}
Another is something like:
public interface IConvertibleToCombinedType
{
CombinedType ConvertToCombinedType();
}
public class SomeType1 : IConvertibleToCombinedType
{
// ... or get rid of the implicit conversion, and put the logic here
public CombinedType ConvertToCombinedType() => this;
}
public class SomeType2 : IConvertibleToCombinedType
{
...
}
void DoSomethingWith<T>(IEnumerable<T> stuff) where T : IConvertibleToCombinedType
{
IEnumerable<CombinedType> converted = stuff.Select(i => ConvertToCombinedType());
...
}
Upvotes: 3
Reputation: 567
You could create a shared dummy interface like interface ICombinedType {}
, make all 3 classes implement it, and then add where T : ICombinedType
to the generic method.
Upvotes: 0