虽然IsAssignableFrom,但通用类型不能转换

时间:2017-04-14 12:47:39

标签: c# casting

我有一个通用的QueryProvider,可以根据请求提供某种类型的数据(序列)。

在提供数据之前,我会检查所请求的类型IsAssignable是否属于我可以提供的类型。

编译器对从int thirdPos = str.IndexesOf(']').Take(3).Last(); IEnumerable<TData>的演员表示满意,但却抱怨将IEnumerable<TResult>投射到TData

TResult

编译器错误CS0030无法转换类型&#39; TData&#39;到&#39; TResult&#39;

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;

为什么将 } else throw new InvalidOperationException("Can't provide data"); return result; } } 投射到IEnumerable<TData>没有问题,但是不可能将TData投射到TResult?

添加一些评论之后 实际上,IEnumerable<TResult>与问题无关。困扰我的是IsAssignable转换没有问题,而直接转换是。

当然,where子句解决了这个问题,但这只会改变一个问题:为什么IEnumerable没有where子句,为什么直接转换需要where子句:

IEnumerable

如果编译器无法证明我的显式演员是不正确的,那么它是否会让我受益?

2 个答案:

答案 0 :(得分:0)

你的问题和你的代码没有排成一行。您的代码未尝试将TData投射到TResult。它试图将IEnumerable<TData>转换为`TResult。

如果IEnumerable<TData>IEnumerable<TResult>有效。 IEnumerable<TData>TResult不会。

答案 1 :(得分:0)

IsAssignableFrom并不真正链接到任何一个,它是运行时检查,而检查编译器的类型是编译时间检查。

它不允许你将TData转换为TResult,因为它无法验证转换,因为这两种类型之间没有定义任何关系。 IEnumerable在此期间是一个接口,因此强制转换可能有效 - 转换接口与转换具体类型参数不同。