我可以将匿名对象传递给期望类型为object的引用参数的方法吗?

时间:2015-02-19 01:56:02

标签: c# .net anonymous-types ref

我想知道为什么第一次调用Bar(ref object)不起作用而第二次调用不起作用。考虑到我以任意方式传递object类型,以匿名类型传递给Foo(object),这看起来很傻。为什么ref与内存位置有关的内容会影响对Bar()的调用?

请考虑以下代码段:

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

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

4 个答案:

答案 0 :(得分:7)

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

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

  

当形式参数是引用参数时,方法调用中的相应参数必须是   由关键字ref 后跟变量引用(§5.3.3)组成,其类型与形式参数相同。

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

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

答案 1 :(得分:5)

为什么要这样?变量b未被声明为方法所期望的object

考虑这个例子:

string s;
GetValue(ref s); // no...

void GetValue(ref object x)
{
    x = 123;
}

答案 2 :(得分:0)

通过不允许带参数的参数类型的函数,编译器实际上阻止了对类型安全的妥协。在以下场景中也会发生同样的情况

    private static void MyMethod(out object MyPara)
    {
        MyPara = new String('x', 10);
    }

    MyClass obj = new MyClass();
    MyMethod(out obj); //compile time error

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

答案 3 :(得分:-1)

类型推断很聪明,但它无法读懂你的想法。因此,仅仅声明var b = new { };根本不足以使编译器理解,您想要的东西,可以作为对象重新传递。

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

将会工作。