我不能使用TryGetValue并将值赋给属性?

时间:2009-11-25 18:58:02

标签: c# dictionary

我正在尝试

myDic.TryGetValue(“username”,out user.Username);

但它不起作用。

这不可能吗?

3 个答案:

答案 0 :(得分:9)

不,来自文档:

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

http://msdn.microsoft.com/en-us/library/t3c3bfhx.aspx

答案 1 :(得分:6)

要继续约翰的回答,请改为:

string username;
if (myDic.TryGetValue("username", out username))
{
  user.Username = username;
}

答案 2 :(得分:3)

您可以在VB中执行此操作,但不能在C#中执行此操作。

VB将生成一个临时变量(在堆栈上),将其地址传递给out值,然后在方法调用后对属性进行赋值。

通常VB会这样做,因为它在整个地方都有很多隐式的东西。这就是它的工作方式。

另一方面,C#倾向于将隐含性作为其哲学的一部分。这就是为什么,例如,您必须向调用站点添加“out”以使参数工作,以及为什么它不支持扩展方法的第一个参数的“ref”参数。

这里可以使用呼叫站点上的显式“out”语法来支持属性。但是,我认为他们不这样做的原因是因为VB使用的技巧对于属性的行为与对于字段的行为不完全相同。对于字段,分配将立即发生在方法内部发生的位置。如果方法中有其他代码读取字段(通过调用对象上的方法),它将读取通过输出参数分配的新字段值。

对于属性,使用VB技巧,直到方法返回后才会分配属性。这意味着在out参数赋值后直接读取属性的任何代码都将读取旧值。

这是我的意思的一个简单例子:

class C
{
    private int m_bar;

    public int Bar { get { return m_bar; } set { m_bar = value; }}

    void foo(out int x)
    {
        x = 2;
        Console.WriteLine(Bar);
    }

    void DoStuff()
    {
        foo(out m_bar); //outputs 2
        Bar = 0;
        //pretend this works
        foo(out Bar); //outputs 0
        Console.WriteLine(Bar); // outputs 2
    }
}

在DoStuff()内部,第一次调用foo会比第二次调用foo时获得不同的行为,尽管大多数人都希望它们的行为方式相同。

通常C#会试图避免这些类型的事情。

这是我猜测为什么他们不支持它(规范只是说不支持,它并没有真正说明原因)。