【问题标题】:Can I pass an anonymous object into a method that expects a reference parameter of type object?我可以将匿名对象传递给需要对象类型的引用参数的方法吗?
【发布时间】:2015-04-20 06:28:51
【问题描述】:

我想知道为什么对Bar(ref object) 的第一次调用不起作用而第二次调用。考虑到我以任何方式传递object 类型似乎很愚蠢, 将匿名类型传递给Foo(object) 工作正常。为什么ref,与内存位置有关的东西会影响对Bar()的调用?

考虑以下 sn-p:

static void Foo(object obj)
{ }

static void Bar(ref object obj)
{ }

static void Main()
{
    // Compiles
    var a = new { };
    Foo(a);

    // Does not compile
    var b = new { };
    Bar(ref b);

    // Compiles
    object c = new { };
    Bar(ref c);
}

我在下面的答案中看到了有关如何编译代码的建议,但这不是我所追求的。我想具体了解为什么在将匿名类型传递给Foo() 时将其设为ref 参数会阻止编译工作正常。

【问题讨论】:

    标签: c# .net anonymous-types ref


    【解决方案1】:

    主要原因有点隐藏:发生这种情况是因为您传入的参数必须与参数中定义的类型完全相同。

    这在规范部分 $10.6.1.2 中有说明(含糊不清?):

    当形参是引用形参时,方法调用中对应的实参必须 由关键字 ref 后跟一个变量引用(第 5.3.3 节)与形参的类型相同

    出于同样的原因,将子类传递给使用引用参数的方法是行不通的。这在 Jeff Mercado 的回答中有所描述。

    在您的第一个示例中,您不使用ref,因此多态性有效(匿名类型是object 的子类型),在最后一个示例中,您将其声明为object,这意味着您使用完全相同的类型作为参考参数。

    【讨论】:

      【解决方案2】:

      为什么要这样做?变量b 没有像方法所期望的那样声明为object

      考虑这个例子:

      string s;
      GetValue(ref s); // no...
      
      void GetValue(ref object x)
      {
          x = 123;
      }
      

      【讨论】:

      • 谢谢。但是匿名传递给Foo(object) 不是问题。为什么将参数设为ref 时会阻止编译?
      • 我可以找到规范,但示例应该非常清楚为什么它应该失败。
      • 谢谢,您的回答同样好,但我很欣赏下面的规范引用。无论如何,谢谢,我赞成这个:)
      【解决方案3】:

      通过不允许带有 ref 和参数类型的函数,编译器实际上是在防止损害类型安全。同样的情况也发生在下面的场景中

          private static void MyMethod(out object MyPara)
          {
              MyPara = new String('x', 10);
          }
      
          MyClass obj = new MyClass();
          MyMethod(out obj); //compile time error
      

      编译器实际上是通过不允许这种情况编译来保持 obj 的内存位置安全。如果允许这样做,应用程序的安全性很容易受到损害

      【讨论】:

        【解决方案4】:

        类型推断很聪明,但它无法读懂你的想法。所以仅仅声明var b = new { }; 是不足以让编译器理解你想要一些可以作为对象引用传递的信息。

        var b = new Object ();
        Bar (ref b);
        

        当然可以。

        【讨论】:

        • 这实际上是不正确的答案——因为其他答案指出任何类型不匹配都会发生同样的错误——这里不涉及类型推断。
        • @AlexeiLevenkov - 在您使用 var 的那一刻,类型推断开始发挥作用 - 这创建类型不匹配。当您向var 提供足够的信息以使其获得正确的类型时,类型不匹配(以及由此产生的编译时错误)就会消失。
        • var 在幕后使用了完全正确的类型,没有错误的推断。通过将匿名类型定义为object,您只需将其向上转换为更通用的规范,该规范确实符合方法的定义。将其创建为对象并不能回答问题,因为现在您不使用匿名类型。
        • @JeroenVannevel - 你的评论是矛盾的!如果var已经使用了拟合类型,如何将其定义为对象使其拟合?
        • 我明白你的意思...确实有 var 的类型推断(看起来 OP 知道它将设置特定类型而不询问该行)。显然代码 after 声明也对声明没有影响 - 所以虽然从技术上讲有推论,但从我的角度来看,它与问题所在的代码行无关。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-22
        • 2020-09-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多