Метод интерфейса Param как справочные задачи - PullRequest
1 голос
/ 29 января 2011

Если у кого-то есть лучший заголовок, дайте мне знать.

Я сделал DisposeHelper, поэтому вместо этого:

private Something _thing;

void Dispose()
{
    if(_thing != null)
    {
        _thing.Dispose();
        _thing = null;
    }
}

... я мог бы сделать это:

private Something _thing;

void Dispose()
{
    DiposeHelper.Dipose(ref _thing);
}

Но, очевидно, я не могу кормить DisposeHelper. Укажите IDisposable как ссылку, если я не приведу Something как IDisposable, например так:

private Something _thing;

void Dispose()
{
    IDisposable d = _thing;
    DiposeHelper.Dipose(ref d);
}

... что означает, что это незатем обнулите исходное поле.

Вот более абстрактный пример.DoThis работает, DoThat не:

public class Test
{
    public Test()
    {
        Something o = new Something();

        DoThis(o);

        DoThat(ref o);
    }

    private void DoThis(IFoo obj) { }

    private void DoThat(ref IFoo obj) { }
}

public class Something : IFoo { }

public interface IFoo { }

Почему я не могу это сделать?

Ответы [ 3 ]

2 голосов
/ 29 января 2011

Не работает, потому что типы параметров для выражений ref и out должны точно совпадать.Представьте себе, если бы DoThat действительно имел такую ​​реализацию:

private void DoThat(ref IFoo obj)
{
    obj = new SomeOtherImplementationOfFoo();
}

Теперь этот код:

Something o = new Something();
DoThat(ref o);

в итоге получит o, ссылаясь на экземпляр SomeOtherImplementationOfFoo вместо Something -что явно не может быть правильным.

Так вот почему ref работает так, как работает - и ответ Роба дает способ обойти это.

2 голосов
/ 29 января 2011

Я не знаю технической причины, почему вы не можете.

Это работает, однако:

var o = new Something();
DoThat(ref o);

private void DoThat<T>(ref T obj) where T : class, IFoo { 
    obj = null;
}
0 голосов
/ 29 января 2011

Это не работает, потому что тип должен быть точным типом свойства.

Представьте, что вы можете передать Derived как Base в функцию по ссылке.Теперь функция назначает параметру новый объект, который является Base, но не Derived.Booom

private Derived d;

void Modify(ref Base b)
{
  b=new Base();
}

Modify(ref d);//Booom

В качестве обходного пути используется общий параметр, как в ответе Роба.

public static void DisposeAndNull<T>(ref T x)
  where T:IDisposable
{
  x.Dispose();
  x=null;
}
...