C# 为什么属性不能作为输出参数传递?
例如:C# 为什么属性不能作为输出参数传递?,c#,.net,parameters,C#,.net,Parameters,例如: int? qID= null; answer.QuestionID = int.TryParse(lblID.Text, out qID.Value) ? qID : null; //Error: Property or Indexer may not be passed as an out ot ref parameter. 从microsoft文档中可以看出: 作为out参数传递的变量不需要初始化。但是,在方法返回之前,必须为out参数赋值 然后: “属性不是变
int? qID= null;
answer.QuestionID = int.TryParse(lblID.Text, out qID.Value) ? qID : null; //Error: Property or Indexer may not be passed as an out ot ref parameter.
从microsoft文档中可以看出:
作为out参数传递的变量不需要初始化。但是,在方法返回之前,必须为out参数赋值
然后:
“属性不是变量,不能作为输出参数传递
那么,底层.net平台设计中禁止通过out设置对象的属性的理由是什么呢?out的值也不必是引用对象-使用值类型完全合法。那么为什么不呢
int qID;
if (int.TryParse(lblID.Text, out qID))
{
answer.QuestionID = qID;
}
else
{
answer.QuestionID = null;
}
以下是实际执行情况:
[System.Security.SecuritySafeCritical] // auto-generated
internal unsafe static Boolean TryParseInt32(String s, NumberStyles style, NumberFormatInfo info, out Int32 result) {
Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
NumberBuffer number = new NumberBuffer(numberBufferBytes);
result = 0;
if (!TryStringToNumber(s, style, ref number, info, false)) {
return false;
}
if ((style & NumberStyles.AllowHexSpecifier) != 0) {
if (!HexNumberToInt32(ref number, ref result)) {
return false;
}
}
else {
if (!NumberToInt32(ref number, ref result)) {
return false;
}
}
return true;
}
属性只是一对名为
get\u Something
和set\u Something
的函数
out
参数引用字段或变量;传递一对函数没有任何意义
;编译器生成一个临时变量,并在调用该方法后将proeprty重新分配给该变量
但是,即使是VB.Net也无法处理您的情况,因为
Nullable.Value
属性是只读的。因为属性是编译器生成的get
和set
方法的语法糖。属性只是一对访问器方法的语法糖,因此您实际上需要的是这里的操作是调用一个方法并将结果值作为引用传递。很明显,这个值不是变量,因此不能绑定到
考虑一个类型Foo
,其属性为Bar
;将该属性用作out
参数本质上类似于此:
Foo foo = new Foo();
SomeFunction(out foo.get_Bar());
显然,不能将值分配给
foo.get_Bar()
!这在VB中有效,但在C#中无效…VB有效地为您创建一个临时局部变量,调用传递局部变量作为参数的方法,然后使用局部变量的值设置属性。C#通常不会为您隐藏这类内容
方法本身需要一个变量作为out
参数。它必须有一个可以写入值的存储位置。不是一个属性,也不是它需要调用的任何东西:只是一个存储位置。属性不满足该要求。因此,方法中的编译器无法做到这一点
因此,编译器要么根据VB用一个临时变量来伪造它,要么根据C#禁用它。我个人更喜欢C#方法——否则它看起来好像每次方法给out参数赋值时,都会设置属性——当然不是这样。不会编译。
int
不是int吗?
@K Ivanov,是的,这是可行的,但是为什么你不能仍然设置属性-这是我的问题..值是只读属性,你不能设置它,的实现完全不相关。它怎么不相关?它在一开始就将传递的参数设置为0,这假设它不是readonlyMax,有任何保证吗无论如何,该属性并不仅仅实现一个getter?例如,公共字符串MyName{get;private set;}。你不能,因此框架设计很有意义。@code4life:你的语句没有意义,编译器可以在编译时检查属性是否已经有setter。我想问你的问题是,TryParse
可以很好的,为什么你要用int
作为qID?Lazarus这只是为了展示这个问题,cODE与现实世界无关。但你是正确的。如果你考虑抛出异常的属性,就会出现另一个有趣的问题。然后,TyPARSE会成功,但是属性可能会阻塞,它会为一些令人困惑的错误让路。或者,如果该方法称为属性设置两次。(首先将其设置为默认值,还可以选择其他设置),例如,TrySomething愉快地假设其out参数可以设置为null,但属性不允许。是的,通过out设置属性应该不会有问题。我想我正在寻找一个解释,解释为什么不能这样做。@Max:一对函数不是指针,不能变成指针。@Max:是什么让y你认为它不应该是一个属性吗?既然方法本身需要一个存储位置-一个变量-你会怎么做来满足这个要求?@Jon,如果VB使用temp局部变量来存储out的输出,为什么同样的东西不适合c#语义?@Max:因为这给人一种错误的印象,依我看。它确实是这样做的看起来每次该方法为它的out参数赋值时,属性都会被设置。事实并非如此,而且很容易引起混淆。我不知道在VB中是否有这样的工作的历史先例,但我个人认为这是一个错误的特性。我仍然不明白为什么不为属性设置一个setter,一个本地temp变量可以被创建为一个低值来存储该值。如果vb这样做,为什么c#不能?这是真的,但是在他的示例中,即使在vb中,如果通过引用传递qID.value,它将编译并在运行时工作,但变量不会用新值更新null