为什么属性不能作为out参数传递?

时间:2011-01-27 17:18:51

标签: 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参数赋值。”

然后:

“属性不是变量,不能作为out参数传递。

那么基础.net平台设计中的原因是什么禁止通过out设置对象的属性? out的值也不一定是参考对象 - 使用值类型完全合法。那为什么不呢?

5 个答案:

答案 0 :(得分:15)

这在VB中有效,但在C#中无效... VB有效地为您创建一个临时局部变量,调用传入局部变量的方法作为参数,然后使用局部变量的值设置属性。 C#通常不会为你隐藏那类东西。

该方法本身需要变量作为out参数。它必须有一个存储位置,它只能写入值。不是属性,也不是它需要调用的任何东西:只是一个存储位置。财产不满足该要求。因此,方法中的编译器无法做到这一点。

因此,编译器必须根据VB使用临时变量伪造它,或者根据C#禁止它。我个人更喜欢C#方法 - 否则它看起来好像每次方法为out参数赋值时,属性都会被设置 - 当然不是这样。

答案 1 :(得分:10)

属性只是一对名为get_Somethingset_Something的函数 out参数引用字段或变量;传递一对函数没有任何意义。

VB.Net can pass properties as ByRef parameters;编译器生成一个临时变量,并在调用方法后重新赋予变量proeprty。

然而,即使VB.Net无法处理您的情况,因为Nullable<T>.Value属性是只读的。

答案 2 :(得分:2)

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; 
    }

答案 3 :(得分:2)

因为属性是编译器生成的getset方法的语法糖。

答案 4 :(得分:2)

属性只是一对访问器方法的语法糖,所以你在这里实际做的是调用一个方法并将结果值作为参考传递。显然,这个值不是变量,所以它不能被绑定。

考虑具有属性Foo的类型Bar;将该属性用作out参数基本上类似于:

Foo foo = new Foo();
SomeFunction(out foo.get_Bar());

显然,无法将值分配给foo.get_Bar()