I have a generic QueryProvider that can provide (sequences of) data of a certain type upon request.
Before providing the data I check if the requested type IsAssignableFrom the type I can provide.
The compiler is satisfied with the cast from IEnumerable<TData>
to IEnumerable<TResult>
, yet it complains about casting TData
to TResult
class MyClass<TData>
{
private IEnumerable<TData> GetSequence() {return Enumerable.Empty<TData>(); }
private TData GetSingleValue() { return default(TData); }
public TResult GetResult<TResult>()
{
TResult result;
if (typeof(TResult).IsAssignableFrom(typeof(IEnumerable<TData>)))
{ // we can Assign IEnumerable<TData> to TResult
IEnumerable<TData> data = GetSequence();
result = (TResult)data;
}
else if (typeof(TResult).IsAssignableFrom(typeof(TData)))
{ // we can assing TData to TResult:
TData data = GetSingleValue();
result = (TResult)data;
Compiler Error CS0030 Cannot convert type 'TData' to 'TResult'
}
else
throw new InvalidOperationException("Can't provide data");
return result;
}
}
Why is there no problem casting to IEnumerable<TData>
to IEnumerable<TResult>
, but is it not possible to cast TData to TResult?
Addition after some comments Indeed, the IsAssignable
has nothing to do with the problem. What baffled me was that the IEnumerable
conversion is no problem, while the direct conversion is.
Of course a where clause solves this problem, but this only changes the question: why can the IEnumerable
do without the where clause, and why does a direct converion need the where clause:
IEnumerable<TData> items = ...;
TData item = items.FirstOrDefault();
TResult result1 = (IEnumerable<TResult>) items; // compile time OK
TResult result2 = (TResult) item; // compile time problem
var obj = (object)item;
TResult result3 = (TResult) obj; // compile time OK;
Could it be that if the compiler can't proof that my explicit cast is incorrect, that it gives me the benefit of the doubt?
Your question and your code are not lining up. Your code is not attempting to cast TData
to TResult
. It is attempting to cast IEnumerable<TData>
to `TResult.
If IEnumerable<TData>
to IEnumerable<TResult>
is valid. IEnumerable<TData>
to TResult
will not be.
IsAssignableFrom isn't really linked to any of this, it is a runtime check, while the type checking the compiler does is, well, a compile time check.
It won't let you cast TData to TResult because it can't verify that cast, because there's no relationship defined between these two types. IEnumerable in the meantime is an interface, so the cast might be presumably valid - casting an interface is not the same as casting a concrete type parameter.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.