【问题标题】:C# cast array to element typeC# 将数组转换为元素类型
【发布时间】:2016-08-23 08:08:03
【问题描述】:

我有一个通用参数 T,它在一个特定情况下是一个数组。是否可以将对象数组转换为typeof(T).GetElementType() 的数组?例如:

public TResult Execute<TResult>()// MyClass[] in this particular case
{
    var myArray = new List<object>() { ... }; //actual type of those objects is MyClass
    Type entityType = typeof(TResult).GetElementType(); //MyClass
    //casting to myArray to array of entityType 
    TResult result = ...;
    return result;    
} 

【问题讨论】:

  • 感谢您的回复,但问题是 Execute 方法是接口的实现,我无法更改其签名或添加新签名。
  • 查看我的回答的修改

标签: c# arrays generics casting


【解决方案1】:

这不是一个好主意。您无法将 TResult 限制为数组,因此使用您当前的代码,有人可以调用 Excute&lt;int&gt; 并获得运行时异常,哎呀!

但是,为什么要从数组开始呢?让泛型参数成为元素本身的类型:

public TResult[] Execute<TResult>()
{
    var myArray = ... 
    return myArray.Cast<TResult>().ToArray();
}

更新:响应您的 cmets:

如果Execute是一个你不能改变的接口方法,那么你可以这样做:

public static TResult Execute<TResult>()
{
    var myArray = new List<object>() { ... };
    var entityType = typeof(TResult).GetElementType();
    var outputArray = Array.CreateInstance(entityType, myArray.Count);
    Array.Copy(myArray.ToArray(), outputArray, myArray.Count); //note, this will only work with reference conversions. If user defined cast operators are involved, this method will fail.
    return (TResult)(object)outputArray;
}

【讨论】:

    【解决方案2】:

    您可以使用扩展方法myArray.Cast&lt;MyClass&gt;().ToArray() 来返回一个MyClass 数组。

    我想你的意思是也返回TResult[]

    public TResult[] Execute<TResult>()//MyClass[] in this particular case
    {
        return myArray.Cast<MyClass>().ToArray();
    }
    

    你需要添加

    using System.Linq;
    

    为了查看这些方法。

    【讨论】:

      【解决方案3】:

      我同意 InBetween 的观点,即这是一个坏主意,但我不知道您的背景以及您为什么需要它。但是你可以这样实现它:

      public TResult Execute<TResult>()// MyClass[] in this particular case
      {
          var myArray = new List<object>() { ... }; //actual type of those objects is MyClass
      
          Type genericArgument = typeof(TResult);
          if (!genericArgument.IsArray)
             // what do you want to return now???
      
          Type elementType = genericArgument.GetElementType();
      
          MethodInfo cast = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(elementType);
          MethodInfo toarray = typeof(Enumerable).GetMethod("ToArray").MakeGenericMethod(elementType);
      
          object enumerable = cast.Invoke(null, new object[]{myArray});
          object array = toarray.Invoke(null, new object[]{enumerable});
      
          return (TResult)array;
      }
      

      这使用reflection 来获取特定通用参数的LINQ 扩展。问题是:如果TResult 不是一个数组,这个方法应该返回什么。似乎存在设计缺陷。

      【讨论】:

      • 非常感谢!我已经实现了非数组TResult(这是默认情况)所以一切都应该正常
      • 我真的不认为它需要参与。 OP 基本上要求参考转换 (object -> realUnderlyingType)。在这种情况下,您可以使用Array.Copy。看看我的回答。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-04
      • 2016-10-29
      相关资源
      最近更新 更多