我已经创建了一个处理对象数组的函数process(Object [])。它适用于任何类型,包括整数和浮点数,只要您先将每个元素打包。我喜欢这个函数来获取未装箱的元素,如果只是在处理之前自己装箱。我该怎么做?
我可以用一些函数来包装,比如process(int [])和process(float []),但这似乎也很麻烦。我已尝试过程(ValueType [])但编译器仍然选择进程(Object [])。
我有C#2.0,但如果有一个很好的3.0解决方案,我希望看到它。
答案 0 :(得分:6)
处理如何运作?最明显的方法签名是:
void ProcessArray<T>(T[] data)
这实际上是“任意类型的数组” - 尽管调用者在编译时需要知道该类型。
但是,根据您使用元素的方式,您可能仍会以拳击结束。也许这没关系,因为你的问题的一部分说:“如果只是在处理之前自己装箱”。如果你对此感到满意,那就太棒了:)。
如果您可以提供有关您正在做的事情的更多详细信息,我们可以提供更多帮助。
答案 1 :(得分:0)
简短的回答:你不能(有用)这样做。泛型可能似乎是解决这个问题的方法,但是一旦你实际使用了通用类型的实例,你就会将它传递给必须接受类对象的方法 - 所以它会被盒装(更糟糕的是,它会是根据您的代码,可能会多次装箱。
如果你想通过一般性地避免拳击获得性能,你需要处理如何处理这些实例并确保所有处理都可以以类型安全的方式进行,尽管通用的方法 - 这并不容易(例如,请参阅Generic Numerics)并且在很大程度上取决于您需要进行的处理。
答案 2 :(得分:0)
static void T(Array a)
{
if (a is int[])
Console.WriteLine("Int");
else
if (a is float[])
Console.WriteLine("Float");
else
....
}
static void Main(){
T(new int[]{30});
float[] a = { 11 };
T(a);
}
答案 3 :(得分:0)
拳击是隐含的。例如:
using System;
namespace MyProg
{
class Program
{
private static void ParamTest(params object[] args)
{
foreach (object o in args)
{
Console.Write(o);
Console.WriteLine(", ");
}
Console.WriteLine();
}
static void Main(string[] args)
{
ParamTest(1, "abc", 2.4, new object());
}
}
}
将打印
1, abc, 2.4, System.Object,
不是通用的!
答案 4 :(得分:0)
嗯,从技术上讲,可能。但出于显而易见的原因,它不是推荐的,也不是有用的。请注意,它也表现不佳,并且不允许直接传递数组。
出于好奇和古怪的缘故,这就是诀窍。它使用TypedReference
和未记录的C#关键字。
public void Process(__arglist)
{
var iterator = new ArgIterator(__arglist);
do
{
TypedReference typedReference = iterator.GetNextArg();
Type type = __reftype(typedReference);
if (type == typeof(int))
{
int value = __refvalue( typedReference,int);
// value is an int
}
else if (type == typeof(string))
{
string value = __refvalue( typedReference,string);
// value is a string
}
else if (type == typeof(double))
{
double value = __refvalue( typedReference,double);
// value is a double
}
// etc.
}
while (iterator.GetRemainingCount() > 0);
}
你可以这样调用这个方法:
Process(__arglist(45, "lol", 42.5));
不框/ unbox值类型。但是,好吧,忘记......