如果可以,我能否将属性作为"out"或"ref"参数传递?如果不行,为什么呢?
例如:
Person p = new Person();
. . .
public void Test(out p.Name);
如果可以,我能否将属性作为"out"或"ref"参数传递?如果不行,为什么呢?
例如:
Person p = new Person();
. . .
public void Test(out p.Name);
out
或ref
参数时,实际上是传递变量的地址(或内存位置)。在函数内部,编译器知道变量的真实位置,并获取并写入该地址的值。你调用的函数应该具有什么样的签名?
假设你想调用void MyFn(ref int i)
,那么它是否应该保持原样,还是应该改为允许属性?如果更改为void MyFn(prop_ref int i)
这样的语法,则相当无用,因为您不能将属性传递给未使用特殊prop_ref
修饰符编写的库函数或第三方代码。无论如何,我认为您建议不应该有所不同。
现在假设MyFn
将i
传递给COM函数或WinAPI调用,通过引用(即在.net之外)。如果它是一个属性,那么你怎么获取i
的地址?也许没有实际的int类型的值可以获取地址。你会像VB.Net一样做吗?
Vb.Net编译器会在将属性作为ByRef参数传递给方法时进行检测。此时,它声明一个变量,将属性复制到变量中,通过引用传递变量,然后在调用方法后,将变量复制回属性中。例如:
MyFunc(myObject.IntProperty)
成为
Dim temp_i As Integer = myObject.IntProperty
MyFunc(temp_i)
myObject.IntProperty = temp_i
MyFunc
返回之前发生,这可能会导致各种问题并引起非常微妙的错误。ref
参数保证不会产生副作用。例如,一个方法可能会在返回之前多次使用+=
来附加到ref string
,并在进行检查时可能会检查该值。该方法的程序员需要知道它的参数是否支持属性,因为在这种情况下,他们需要创建一个临时变量。 - hypehuman其它人已经解释过在C#中你无法这样做。而在VB.NET中,即使使用了option strict/explicit也可以实现:
Option Strict On
Option Explicit On
Imports System.Text
Module Test
Sub Main()
Dim sb as new StringBuilder
Foo (sb.Length)
End Sub
Sub Foo(ByRef x as Integer)
End Sub
End Module
using System.Text;
class Test
{
static void Main()
{
StringBuilder sb = new StringBuilder();
int tmp = sb.Length;
Foo(ref tmp);
sb.Length = tmp;
}
static void Foo(ref int x)
{
}
}
Option Strict On
Option Explicit On
Imports System.Text
Class Test
Dim counter as Integer
Property CounterProperty As Integer
Get
Return counter
End Get
Set (ByVal value as Integer)
counter = value
End Set
End Property
Sub Increment
counter += 1
End Sub
Shared Sub Main()
Dim t as new Test()
Console.WriteLine("Counter = {0}", t.counter)
t.Foo(t.counter)
Console.WriteLine("Counter = {0}", t.counter)
t.CounterProperty = 0
Console.WriteLine("CounterProperty = {0}", t.CounterProperty)
t.Foo(t.CounterProperty)
Console.WriteLine("CounterProperty = {0}", t.CounterProperty)
End Sub
Sub Foo(ByRef x as Integer)
x = 5
Increment
Increment
Increment
x += 1
End Sub
End Class
.Net-Fiddle: https://dotnetfiddle.net/ZPFIEZ(字段和属性有不同的结果)
相反,你应该做像这样的事情
WhatEverTheType name;
Test(out name);
// Choose one of the following construction
Person p = new Person();
p.Name = name;
Person p = new Person(name);
Person p = new Person(Name => name);