方法接口参数作为参考问题

时间:2011-01-29 11:53:59

标签: c# dispose

如果有人有更好的头衔,请告诉我。

我做了一个DisposeHelper而不是这个:

private Something _thing;

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

......我可以这样做:

private Something _thing;

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

但显然我不能提供DisposeHelper.Dispose一个IDisposable作为参考,除非我把某些东西作为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 个答案:

答案 0 :(得分:2)

我不知道为什么你不能的技术原因。

然而,这是有效的:

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

private void DoThat<T>(ref T obj) where T : class, IFoo { 
    obj = null;
}

答案 1 :(得分:2)

它不起作用,因为refout表达式的参数类型必须完全匹配。想象一下,如果DoThat实际上有这个实现:

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

现在这段代码:

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

最终会o引用SomeOtherImplementationOfFoo而不是Something的实例 - 这显然不是正确的。

这就是为什么ref按照它的方式工作的原因 - 而Rob的答案提供了一种解决方法。

答案 2 :(得分:0)

它不起作用,因为类型必须是属性的确切类型。

想象一下,您可以通过引用将Derived作为Base传递给函数。现在,该函数为参数指定一个新对象,该对象为Base但不是Derived。 Booom

private Derived d;

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

Modify(ref d);//Booom

解决方法是使用泛型参数,如Rob的回答。

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