c# - 为什么我不能将不同数量的引用传递给一个函数?

标签 c# .net parameters ref

我想做这样的事情:

double a, b, c, d, e;
ParseAndWrite("{1, 2, 3}", ref a, ref b, ref c);
ParseAndWrite("{4, 5}", ref d, ref e);

-> a = 1, b = 2, c = 3, d = 4, e = 5

但是,我不能写这样的函数:

private void ParseAndWrite(string leInput, params ref double[] targets)
{
   (...)
}

这行不通,出于某种原因不能同时使用 ref 和 params。为什么会这样?

编辑:好的,这里有一些关于我为什么需要这个的更多信息:通过一个接口(interface),我得到了很多包含值的字符串,语法如下:

inputConfig : " step, stepHeight, rStep, rStepHeight, (nIterations, split, smooth) "
outputConfig : " dataSelection, (corrected, units, outlierCount, restoreOriginalRange) "

(括号中的名称是可选的)。这些值需要被解析并存储在所有特定变量中。也就是说——它们根本不是数组。它们更像是命令行参数,但大约有 20 个。我当然可以按顺序执行所有这些操作,但这会产生数百行包含冗余模式且难以维护的代码。

最佳答案

for some reason one can not use ref and params at the same time. Why so?

考虑相机的这三个理想特性:

  1. 轻量级

  2. 高品质镜头

  3. 便宜

在任何相机中您最多只能拥有两个。你永远不会得到所有三个。您可以获得廉价的重型大镜头相机,或昂贵的轻型大镜头相机,或便宜的轻型快照相机,但没有带大镜头的廉价轻型相机。

现在回到你的问题。考虑运行时的这三个理想特征:

  1. ref-to-variable 类型的参数数组是合法的

  2. 类型系统是安全的

  3. 具有引用的局部变量仍然可以快速分配和释放

你可以拥有任何两个,但你不能拥有所有三个。你想要哪两个?

您可以拥有引用参数数组和安全类型系统,代价是将引用的局部变量分配到垃圾收集堆上。据我所知,没有人这样做,但这当然是可能的。

你可以有 ref param 数组,分配在临时池上的所有局部变量,以及一个当你使用错误时崩溃的类型系统。这是“C/C++”方法;可以获取引用并将其存储在生命周期比被引用事物的生命周期更长的位置。如果这样做,您可能会犯下难以检测的简单错误,从而导致 C++ 程序崩溃并以最可怕的方式死亡。欢迎来到绝望的深渊。

或者我们可以使 ref param 数组非法,在临时池上分配所有局部变量,并拥有一个可验证内存安全的类型系统。这是我们在构建 C# 和 CLR 时做出的选择;欢迎来到质量的坑。


现在,我上面所说的实际上都是一个弥天大谎。这是一个谎言,因为运行时和 C# 语言实际上确实支持类似于(但不完全相同)refs 参数数组的功能。这是一个令人愉快的谎言,相信我,你想生活在你相信谎言的世界里,所以我建议你服用蓝色药丸并继续这样做。

如果您想采取红色药丸并找出兔子洞有多深,您可以使用 C# 的未记录的 __arglist 功能构建一个C 风格的可变参数方法,然后制作 TypedReference 对象,引用任意字段的引用或结构类型的局部变量,然后将任意多个对象传递给可变参数方法。使用 TypedReference 的工厂方法或 C# 的未记录的 __makeref 功能。

我们在过去十年中一直未对这些功能进行记录的原因是,根据设计,它们仅用于极其罕见的情况,在这些情况下,您必须编写与用其他语言编写的可变参数方法干净地互操作的 C# 代码。

正确使用 TypedReference 对象并不适合胆小的人,我再次强烈建议不要这样做。在多年编写 C# 的过程中,我从未在生产代码中这样做过。如果您想传递对任意多个变量的引用,传递一个数组。根据定义,数组是变量的集合。这比传递一堆表示实例或局部变量的托管地址的对象要安全得多。

关于c# - 为什么我不能将不同数量的引用传递给一个函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8416740/

相关文章:

c# - 如何通过 T4 自动化为每个实体生成我的所有实体组成的两个表

c - 将无符号字符数组作为参数传递 - 数组未正确传递

c# - 在 C# 中从 SQL Server 插入和检索 ByteArray

c# - 查找服务设置为哪个帐户 "Log On As"

javascript - 如何在 $.ajax (type get) 调用中获取方法的返回值?

c# - 如何通过主键和外键(右连接)合并两个数据表?

c++ - 数字为 std::string 还是 double?

c - 双参数数组排序

C# 如何转义 eval <%?

c# - 如何在 C# 中存储不同通用事物的列表