2009-09-30 3 views
5

Когда формальный аргумент метода имеет тип «объект», для фактического аргумента возможен любой тип объекта, через наследование. Как только в методе объект может быть добавлен к ожидаемому типу. Все в порядке.Объекты, параметры и ключевое слово ref в C#

Если, однако, подпись метода имеет формальный аргумент «объекта», используя реф ключевое слово т.е. имяМетода (ссылка объекта), компилятор выдает ошибку о том, что:

«лучший перегруженный метод матч за «ByRefTest.Program.changeMeByRef (ссылка объекта)» имеет некоторые недопустимые аргументы «Аргумент„1“: не удается преобразовать из„исх ByRefTest.Person“до„исх объекта“».

разница между использованием или нет используя ref keword при передаче объектов, поскольку параметры очень хорошо объясняются в блоге А. Фридмана http://crazorsharp.blogspot.com/2009/07/passing-objects-using-ref-keywordwait.html, но почему невозможно передать пользовательский тип в качестве фактического аргумента, когда Формальный аргумент типа «объект» использует ключевое слово 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 
{ 
} 

Спасибо.

п.с. я просто изменил подпись:

государственной статической силы changeMeByRef <T> (исх T объект), где T: Person

это составляет для changeMeByRef (исх р);

+0

Это дубликат http://stackoverflow.com/questions/1207144/c-why-doesnt-ref-and-out-support-polymorphism/1207302#1207302 –

ответ

8

Поскольку метод может изменить параметр, чтобы иметь значение другого типа, в нарушение типа переменной, используемой для аргумента. Простой пример:

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

... 

// This doesn't compile, fortunately. 
Stream y = null; 
Foo(ref y); 

Что значение y после присваивания в методе? Он должен быть строкой, но это нарушает тип переменной. Это была бы очень плохая вещь, полностью нарушая безопасность типов. Это та же самая причина для общей инвариантности IList<T> даже в .NET 4.0.

Eric Lippert recently blogged about the invariance of ref in more detail.

2

Поскольку параметр ref работает в обоих направлениях. Вы можете назначить параметр произвольному объекту внутри вашей функции, а код вызова должен обрабатывать его.

0

сделать это. легче.
changeMe (p); // компилирует
changeMeByRef (ref (Object) p); // на этот раз он не должен бросать ошибки.

+0

@behrooz: Вы попробовали это? Вы не можете использовать аргумент ref. –

Смежные вопросы