【问题标题】:How to cast an object to a generic return type, when the return type is a generic interface?当返回类型是泛型接口时,如何将对象转换为泛型返回类型?
【发布时间】:2015-12-31 06:55:17
【问题描述】:

我有一个非常丑陋的方法,它应该从数据库中提取各种数据,并使用它构造一个请求类型的对象。目标是将各种丑陋的东西拉到一个地方,以便从包含该方法的类派生的类可以相对干净。

我对何时应该返回单个对象没有问题,即使该类型可以为空:

protected T getValue<T>(ParameterObject myParameterObject)
{
    var typeOfT = typeof (T);

    if (typeOfT == typeof(bool))
    {
        string val = this.getValue(myParameterObject);

        if (val == null)
            return default(T);

        bool rVal;
        if (!Boolean.TryParse(val, out rVal))
            return default(T);

        return changeType<T>(rVal);
    }

    if (typeOfT == typeof (double?))
    {
        string val = this.getValue(myParameterObject);

        if (val == null)
            return default(T);

        double rVal;
        if (!Double.TryParse(val, out rVal))
            return default(T);

        return changeType<T>(rVal);
    }

    [...]
}

public static T changeType<T>(object value)
{
    var t = typeof(T);
    if (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(Nullable<>))
        return (T)Convert.ChangeType(value, t);

    if (value == null)
        return default(T);

    t = Nullable.GetUnderlyingType(t);
    return (T)Convert.ChangeType(value, t);
}

不幸的是,在某些情况下,我想要的返回类型是 IList,我想在其中返回一个 List:

protected T getValue<T>(ParameterObject myParameterObject)
{
    var typeOfT = typeof (T);

    if (typeOfT.IsGenericType)
    {
        if (typeOfT.GetGenericTypeDefinition() == typeof (IList<>))
        {
            var genericArgumentType = typeOfT.GenericTypeArguments.FirstOrDefault();
            var baseType = typeof (List<>);
            var genericType = baseType.MakeGenericType(new[] {genericArgumentType});

            var rVal = Activator.CreateInstance(genericType);

            [code to populate the list] 

            return changeType<T>(rVal);
        }

    [...]
}

我无法返回 rVal,因为它是一个对象,而不是 T 的实例。但是我的 changeType() 函数失败了,并出现错误:

System.InvalidCastException:对象必须实现 IConvertible。

所以,我有一个返回类型为 IList 的泛型方法,我有一个 List 对象,但我对它的引用是 Object 类型。如何转换它以便我可以从函数中返回它?

【问题讨论】:

  • 对不起,如果我遗漏了一些明显的东西,但你为什么要使用 return changeType&lt;T&gt;(rVal); 而不是 return (T)(object)rVal;

标签: c# generics iconvertible


【解决方案1】:

您的return (T)Convert.ChangeType(value, t); 行失败,因为您的value 对象没有实现IConvertible

来自MSDN docs

[...] 为使转换成功,value 必须实现IConvertible 接口,因为该方法简单地包装了对适当IConvertible 方法的调用。该方法要求支持将 value 转换为 conversionType。

要解决此问题,我不确定一般方法,但对于 value 属于 IEnumerableIEnumerable&lt;&gt; 类型的特定情况,您可以尝试强制转换然后执行 value.Select(x =&gt; changeType&lt;ListGenT&gt;(x)) linq询问。通过递归使用您的 changeType 方法,这也应该可以处理嵌套的泛型类型。

【讨论】:

  • 我仍然不确定我是否理解,但如果我将方法更改为返回 List,而不是创建 List 并返回 IList,问题就消失了.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 2016-10-16
  • 1970-01-01
  • 2019-06-29
  • 2013-01-08
  • 2015-05-20
  • 1970-01-01
相关资源
最近更新 更多