将任意值类型的数组作为形参

发布于 2024-07-13 18:47:33 字数 589 浏览 11 评论 0原文

我希望能够像

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

C# 2.0 中那样声明一个函数。 如果我在

void foo(ValueType[] data){}

编译时声明它,但 data[] 中的元素会被视为派生自 object,例如,我不能说类似“

fixed (void* pData = data){}

我想避免采用void* 作为参数——我只是希望能够接受任何值类型数组,然后对其执行非托管操作。

ETA:另外,这也有同样的问题:

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

如果你想知道的话。 修复失败,因为它被视为托管类型 - CS0208,无法声明指向托管类型的指针。 参见下面的“毫米”。 我认为他是对的...这可能只是无法完成。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

玩物 2024-07-20 18:47:33

我认为使用 C# 不可能做到这一点。 直到编译时间之后,结构才会从 System.ValueType 继承(无论多么松散),因此您无法通过多态性匹配 Foo 的方法签名。 泛型也根据语言规范被淘汰:

“非托管类型是指不是引用类型、类型参数或泛型结构类型的任何类型,并且
不包含任何类型不是非托管类型的字段。”

因此,无论结构约束如何,您都无法获取 T[] 的地址。

您可以声明一个结构类型(例如 Bar)作为 Foo 的参数,编译代码,并在 IL 级别更改方法签名:

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

然后也是调用:

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

虽然我能够运行生成的程序,但我也不知道这会产生什么样的副作用。 ,即使您可以引用修改后的函数,您也无法从 C# 调用它,因为在编译之前结构不会从 System.ValueType 继承,因此方法签名不匹配。

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.

白云不回头 2024-07-20 18:47:33
public void foo<T>(params T[] args) where T : struct {
}
public void SomeMethod() {
    foo(1, 2, 3, 4);
}

您不必输入泛型参数,因为编译器将从 foo 的第一个参数中获取类型。

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.

白云不回头 2024-07-20 18:47:33

这是可行的:

    public static void foo(System.Array data)
    {

    }

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

它不会强制该数组是值类型的数组,但它会起作用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文