在运行时测试传入的 ByRef 参数是不是与给定的“其他”变量共享存储位置
Posted
技术标签:
【中文标题】在运行时测试传入的 ByRef 参数是不是与给定的“其他”变量共享存储位置【英文标题】:Test at runtime if a passed in ByRef parameter shares storage location with a given "other" variable在运行时测试传入的 ByRef 参数是否与给定的“其他”变量共享存储位置 【发布时间】:2013-06-27 16:21:12 【问题描述】:这个问题更多是出于好奇而不是出于实际需要。
有什么方法可以测试传入ByRef
(即C# 中的ref
或out
)参数的参数是否与某个“其他”变量具有相同的存储位置?我并不是要测试对象是否相同,因为两个不同的引用变量可能是对同一对象的两个不同的引用。
我想出了一些例子来解释我的意思。考虑:
public static void SillySwap(ref int a, ref int b)
// first put sum of original numbers into slot a,
// then use that to get out the original numbers swapped
a = a + b;
b = a - b;
a = a - b;
(我们通常会使用第三个临时变量,但为了说明我的问题,我会这样做。)SillySwap
如果您使用 两个 变量(相同或不同)就可以正常工作在数值上。但如果你这样称呼它:
int shared = 42;
SillySwap(ref shared, ref shared);
它将消灭shared
。 如果a
和b
与存储位置相同,我有什么方法可以在SillySwap
的内部进行测试?
这是一个带有字段(“类变量”)的修改示例:
protected static int field;
public static void SillySwap2(ref int arg)
arg = arg + field;
field = arg - field;
arg = arg - field;
这里我们要检查传入的arg
是否真的是变量field
。
最后一个例子,考虑这个:
static bool SillyTryGetStrings(out string first, out string second)
// the order of assignment may matter here!
second = "world";
first = "Hello";
return true;
假设某个陌生人为first
和second
传入了同一个变量。我们可以在方法中检查它吗?
【问题讨论】:
【参考方案1】:一种方法是使用不安全的代码并比较指向变量的指针:
public unsafe bool AreRefsEqual(ref int a, ref int b)
fixed (int* aptr = &a)
fixed (int* bptr = &b)
return aptr == bptr;
[TestMethod]
public void ShouldRefsEqualWork()
int a = 1, b = 1;
Assert.IsTrue(AreRefsEqual(ref a, ref a));
Assert.IsFalse(AreRefsEqual(ref a, ref b));
【讨论】:
非常有趣。您的unsafe
方法是否可以通用以适用于所有值类型和引用类型,而不仅仅是 int
?
我不认为它可以在 c# 中完成,因为无论约束如何,您都无法获取泛型类型的地址(您只能获取少数类型的地址)。我认为这在 C++/CLI 中是可能的。
所以你的解决方案只是部分的。它有一些限制。 (1) 它仅适用于值类型(并且仅适用于没有引用类型的实例字段的值类型)。 (2)我认为,使用未分配变量的一元&
运算符获取地址是合法的,所以如果我有一个out int i
参数并且想在开始时检查它的地址,我可以使用你的代码“ inline”,但我认为它不允许我将 i
传递给您的 AreRefsEqual
方法,因为它不是绝对分配的。以上是关于在运行时测试传入的 ByRef 参数是不是与给定的“其他”变量共享存储位置的主要内容,如果未能解决你的问题,请参考以下文章
在 Android Studio 中运行参数化单元测试时,未找到给定的测试包括错误
optional [byval byref] [paramarray] 变量名() as 数据类型
从被调用的函数调用函数时 VBA byref 参数类型不匹配