Reputation: 2971
I've made a function that processes an array of objects, process(Object[]). It works on any type including integers and floats so long as you box each element first. I'd like the function to take unboxed elements aswell, if only to box it itself before processing. How do I do that?
I could wrap with a few functions like process(int[]) and process(float[]) but that also seems a hassle. I've tried process(ValueType[]) but the compiler still selects process(Object[]).
I have C# 2.0, but if there is a nice solution for 3.0 I'd like to see it.
Upvotes: 5
Views: 3585
Reputation: 13011
Well, technically, it is possible. But it's not recommended, nor useful, for obvious reasons. Note that it performs badly too, and doesn't allow you pass arrays directly.
For curiosity and weirdness sake, here is the trick. It uses TypedReference
and undocumented C# keywords.
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);
}
You can call the method like that:
Process(__arglist(45, "lol", 42.5));
It will not box/unbox values types. But, well, forget that...
Upvotes: 0
Reputation: 1503819
How does the processing work? The most obvious method signature would be:
void ProcessArray<T>(T[] data)
That is literally "an array of an arbitrary type" - although the type needs to be known by the caller at compile-time.
However, depending on how you use the elements, you may still end up boxing. Maybe that's okay, given the part of your question which says: "if only to box it itself before processing". If you're happy enough with that, great :)
If you could give more details of what you're doing, we may be able to help more.
Upvotes: 7
Reputation: 99520
Boxing is implicit. For example:
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());
}
}
}
will print
1, abc, 2.4, System.Object,
Not a generic in sight!
Upvotes: 0
Reputation: 48166
Short answer: you can't (usefully) do this. Generics might seem to be a way around this, but as soon as you actually use the generically typed instance, you'll be passing it to methods that must accept class object - so it'll be boxed then (worse; it'll be boxed many times probably, depending on your code).
If you want to gain performance by avoiding boxing generically, you'll need to work on how you process these instances and ensure that all processing can occur in a type-safe manner despite the generic approach - and that's not easy (see Generic Numerics for example) and depends heavily on the processing you need to do.
Upvotes: 0
Reputation: 94653
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);
}
Upvotes: 0