gpt4 book ai didi

c# - 下层调用者是否能够从使用 C# 4.0 生成的程序集中的可选参数中获益?

转载 作者:太空宇宙 更新时间:2023-11-03 11:54:35 25 4
gpt4 key购买 nike

假设我有一个现有程序集,并且一些类具有重载方法,其中一些重载具有默认行为或假定值。我认为这是一个非常典型的模式;

Type2 _defaultValueForParam2 = foo;
Type3 _defaultValueForParam3 = bar;

public ReturnType TheMethod(Type1 param1)
{
return TheMethod(param1, _defaultValueForParam2);
}
public ReturnType TheMethod(Type1 param1, Type2 param2)
{
return TheMethod(param1, param2, _defaultValueForParam3);
}
public ReturnType TheMethod(Type1 param1, Type2 param2, Type3 param3)
{
// actually implement the method here.
}

而且我知道 C# 中的可选参数应该让我将其合并为一个方法。如果我生成一个带有一些标记为可选参数的方法,它是否可以与程序集的下层调用者一起使用?


编辑:我所说的“工作”是指,一个下层调用者,一个用 C# 2.0 或 3.5 编译器编译的应用程序,将能够调用一个方法,两个或三个参数,就像我使用了重载一样,下层编译器不会提示。

我确实想重构并消除我的库中的所有重载,但我不想强制使用重构库的下层调用者提供每个参数。

最佳答案

我还没有阅读有关新语言标准的文档,但我假设您的 4.0 之前的调用者必须像现在一样传递所有 声明的参数。这是因为参数传递的工作方式。

当你调用一个方法时,参数被压入堆栈。如果传递了三个 32 位参数,那么 12 个字节将被压入堆栈;如果传递了四个 32 位参数,则 16 个字节将被压入堆栈。压入堆栈的字节数隐含在调用中:被调用方假定传递了正确数量的参数。

因此,如果一个函数有四个 32 位参数,它将在堆栈中查找调用者返回地址之前的 16 个字节。如果调用者只传递了 12 个字节,那么被调用者将读取 4 个字节,即在调用之前已经在堆栈上的任何内容。它无法知道所有 16 个预期字节均未通过。

这就是它现在的工作方式。对于现有的编译器,没有任何改变。

要支持可选参数,必须发生以下两种情况之一:

  1. 调用者可以传递一个额外的值,明确地告诉被调用者有多少参数(或字节)被压入堆栈。然后,被调用方可以为任何省略的参数填写默认值。
  2. 调用者可以继续传递所有已声明的参数,用默认值(将从被调用者的元数据中读取)替换代码中省略的任何可选参数。被调用者然后从堆栈中读取所有参数值,就像现在一样。

我怀疑会像上面(2)那样实现。这类似于它在 C++ 中的完成方式(尽管 C++ 缺少元数据,需要在头文件中指定默认参数),比选项 (1) 更有效,因为它都是在编译时完成的,而不是需要一个额外的值才能压入堆栈,这是最直接的实现。选项 (2) 的缺点是,如果默认值更改,则必须重新编译所有调用方,否则它们将继续传递旧的默认值,因为它们已作为常量编译。这类似于公共(public)常量现在的工作方式。请注意,选项 (1) 没有此缺点。

选项 (1) 也不支持命名参数传递,因此给定一个这样声明的函数:

static void Foo(int a, int b = 0, int c = 0){}

可以这样调用:

Foo(1, c: 2);

可以修改选项 (1) 以允许这样做,方法是使额外的隐藏值成为省略参数的位图,其中每一位代表一个可选参数。这任意限制了函数可以接受的可选参数的数量,尽管考虑到此限制至少为 32,这可能不是一件坏事。然而,这确实使实际实现变得极不可能。

给定任一实现,调用代码必须理解可选参数的机制,以便在调用中省略任何参数。此外,对于选项 (1),必须传递一个额外的隐藏参数,旧的编译器甚至不知道它,除非它作为正式参数添加到元数据中。

关于c# - 下层调用者是否能够从使用 C# 4.0 生成的程序集中的可选参数中获益?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/983152/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com