C#中的对象,参数和ref关键字

iWe*_*sel 5 .net c#

当方法的形式参数是'object'类型时,通过继承,实际参数可以是任何对象类型.一旦进入方法,对象就可以转换为预期的类型.一切都很好.

但是,如果方法的签名具有'object'的形式参数,则使用ref关键字即methodname(ref object),编译器会抛出一个错误,指出:

"'ByRefTest.Program.changeMeByRef(ref object)'的最佳重载方法匹配'有一些无效的参数."Argument'1':无法从'ref ByRefTest.Person'转换为'ref object'"

在将对象作为参数传递时使用或不使用ref keword之间的区别在A. Friedman的博客http://crazorsharp.blogspot.com/2009/07/passing-objects-using-ref-keywordwait.html中有很好的解释,但是,当'object'类型的形式参数使用ref关键字时,为什么不能将自定义类型作为实际参数传递?

举个例子:

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();

        changeMe(p); // compiles
        changeMeByRef(ref p); // throws error

        object pObject = (object)p;
        changeMeByRef(ref pObject); // compiles
    }


    public static void changeMeByRef(ref object obj)
    {
        Person p = (Person)obj;
    }

    public static void changeMe(object obj)
    {
        Person p = (Person)obj;

    }
}

public class Person
{
}
Run Code Online (Sandbox Code Playgroud)

谢谢.

ps我刚刚将签名更改为:

public static void changeMeByRef <T>(ref T obj)其中T:Person

这为changeMeByRef(ref p)编译;

Jon*_*eet 8

因为该方法可能会将参数更改为具有不同类型的值,这违反了用于参数的变量的类型.简单的例子:

public void Foo(ref object x)
{
    x = "hello";
}

...

// This doesn't compile, fortunately.
Stream y = null;
Foo(ref y);
Run Code Online (Sandbox Code Playgroud)

y在方法中赋值后的值是多少?它应该是一个字符串 - 但这违反了变量的类型.这将是一件非常糟糕的事情,完全违反了类型安全.IList<T>即使在.NET 4.0中,这也是通用不变性的原因.

Eric Lippert 最近在博客上发表了关于不变性的ref更多细节.