views:

332

answers:

3

I would like to be able to declare a function as

void foo(<any value type>[] data){}

in C# 2.0. If I declare it as

void foo(ValueType[] data){}

it compiles, but then the elements in data[] are treated as though they're derived from object, e.g. I can't say something like

fixed (void* pData = data){}

I'd like to avoid taking the void* as the parameter -- I just want to be able to accept any value-type array and then do unmanaged things to it.

ETA: Also, this has the same problem:

public static unsafe void foo<T>(T[] data) where T:struct{
  fixed(void *p = data){}
}

in case you were wondering. Fixed fails because it's treated as a managed type -- CS0208, cannot declare a pointer to a managed type. See "mm" below. I think he's right... it probably just can't be done.

A: 

This would work:

    public static void foo(System.Array data)
    {

    }

    static void Main(string[] args)
    {
        foo(new int[10]);  
    }

It doesn't enforce that the array is an array of value types, but it would work.

epotter
A: 
public void foo<T>(params T[] args) where T : struct {
}
public void SomeMethod() {
    foo(1, 2, 3, 4);
}

You shouldn't have to enter the generic parameter because the compiler will pick up on the type from the first parameter of foo.

Wili
+3  A: 

I don't think this is possible using C#. Structs do not inherit (however loosely) from System.ValueType until after compile time so you can't match Foo's method signature via polymorphism. Generics are also out according to the language specification:

"An unmanaged-type is any type that isn’t a reference-type, a type-parameter, or a generic struct-type and contains no fields whose type is not an unmanaged-type."

So that's why you can't take the address of T[] regardless of the struct constraint.

You could declare a struct type (say, Bar) as the argument to Foo, compile the code, and change the method signature at the IL level:

.method private hidebysig static void Foo(valuetype [mscorlib]System.ValueType[] args) cil managed

And then the call as well:

IL_0020: call void ConsoleApplication1.Program::Foo(valuetype [mscorlib]System.ValueType[])

While I was able to run the resulting program I don't know what kind of side effects this has. Also, even if you could reference the modified function you wouldn't be able to call it from C# because again structs don't inherit from System.ValueType until after compilation so the method signature wouldn't match.

mm