C#: 将 T 转换为 T[]

3
如果T是一个数组,我希望将其转换为T[]。
static T GenericFunction<T>(T t)
{
       if (t == null) return default(T);

       if (t.GetType().IsArray)
       {
            //if object is an array it should be handled
            //by an array method
            return (T) GenericArrayFunction((T[])t); 
       }
       ...
}

static T[] GenericArrayFunction<T>(T[] t)
{
       if (t == null) return default(T);

       for (int i = 0 ; i < t.Length ; i++) 
       {
            //for each element in array carry
            //out Generic Function
            if (t[i].GetType().IsArray())
            {
                 newList[i] = GenericArrayFunction((T[])t[i]); 
            }
            else
            {
                 newList[i] = GenericFunction(t[i]);
            }
       }
       ...
}

错误 如果我尝试使用(T[])t

无法将类型'T'转换为'T[]'

错误 如果我只是尝试传递t

方法'GenericArrayFunction(T[])'的类型参数无法从使用中推断出来。请尝试明确指定类型参数。


3
如果 T 是一个数组,那么 T[] 就是一个二维数组。这可能不是你所期望的。 - Gabe
2
如果T是一个数组,那么T[]就是一个数组的数组。我怀疑这不是你想要的。你是不是想说,如果T是一个未知元素类型U的数组,那么你想要的类型是"U的数组"U[] - jalf
2
你想解决什么问题?你所问的并没有意义,因此为了解决它,你需要退一步告诉我们问题是什么,而不仅仅是问为什么你的解决方案是错误的。 - jalf
3个回答

4
从你举的例子来看,你可不可以定义两个方法,让编译器在传递数组时自动选择正确的方法?
using System;

class Program
{
    static T GenericFunction<T>(T t)
    {
        Console.WriteLine("GenericFunction<T>(T)");
        return default(T);
    }

    static T[] GenericFunction<T>(T[] t)
    {
        // Call the non-array function
        for(int i = 0; i < t.Length; ++i)
            t[i] = GenericFunction(t[i]);

        Console.WriteLine("GenericFunction<T>(T[])");
        return new T[4];
    }

    static void Main()
    {
        int[] arr = {1,2,3};
        int i = 42;

        GenericFunction(i);   // Calls non-array version
        GenericFunction(arr); // Calls array version
    }
}

1
除非原帖作者没有解释一些隐藏的复杂性,否则这将是非常好的。 - Rusty
问题在于,如果我传入 int[] i = {...},object o = i。使用 GenericFunction(o) 将无法调用正确的数组函数。 - user295190
1
@Shiftbit,如果你想要疯狂一点的话……int[] i = {...}; object o = i; GenericFunction((dynamic) o)……可以工作。当然,涉及到dynamic就是完全不同的事情了。 - Rusty

2
仅仅因为T是一个数组类型,并不意味着它也是T的数组。事实上,唯一可能发生的情况是T是像objectArray或者数组实现的接口之类的东西。
你真正想做什么?我猜测你想找到数组的元素类型,然后使用适当的T调用GenericArrayFunction,但这并不会是相同的T,你需要使用反射来调用它,这会有些痛苦。(不是太糟,但不愉快。)
猜测你并没有完全理解C#/.NET泛型——请给我们更多关于整体情况的上下文,这样我们可以更好地帮助你。
编辑:反射方法应该像这样:
private static readonly ArrayMethod = typeof(NameOfContainingType)
    .GetMethod("GenericArrayFunction", BindingFlags.Static | BindingFlags.NonPublic);

...

static T GenericFunction<T>(T t)
{
       if (t == null) return default(T);

       if (t is Array)
       {
           Type elementType = t.GetType().GetElementType();
           MethodInfo method = ArrayMethod.MakeGenericMethod(new[] elementType);
           return (T) method.Invoke(null, new object[] { t });
       }
       ...
}

请注意,这仍然会对矩形数组失败,而且更难处理。

我正在尝试将T传递给GenericArrayFunction。您能否请解释如何使用反射调用它? - user295190
我希望能够在运行时传递参数。如果参数是一个数组,我想进行数组操作,否则进行默认操作。 - user295190
@Shiftbit:你需要提供更多的信息,以便明确你真正想要做什么。 - Jon Skeet
谢谢Jon Skeet。这就是我一直在寻找的解决方案。我正在使用Activator.CreateInstance方法。然而,这种方法不适用于数组,因此我需要使用Array.CreateInstance并在不同的方法中处理它。这些方法都是动态的。这是一个很好的答案。我只需要处理数组级别。 - user295190

2

这是不可能的。 T 永远不能是 T[]T 总是确定的类型,而不仅仅是占位符。如果 T 是数组 (int[]),那么 T[] 将会是 int[][]

编辑:有一些例外情况(比如 objectobject[]),但通常情况下(这就是泛型的作用),T 无法是 T[]。


object[] 是一个 object。所以你可以调用 GenericFunction<object>(new object[5])。但是,这很不可能。 - Jon Skeet
@Jon Skeet 我看了你的回答后就明白了 :) 但是在一般情况下(这也是泛型的作用),T 不能是 T[]。 - Andrey
相关的是,T 可以提供一个隐式转换运算符到 T[],尽管这不能用泛型约束来表达。然而,可以编写 class Foo : IEnumerable<Foo> 并在单独的约束中表达 where T : IEnumerable<T>,从而接受 Foo - Ani
一般情况下,T根本不是一个数组。这并不意味着“不可能”。但条件可以改为if(T is T[]),有可能... - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接