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

C# 方法接口参数作为参考问题,c#,dispose,C#,Dispose,如果有人有更好的头衔,请告诉我 我做了一个处置帮助者,所以不是这样: private Something _thing; void Dispose() { if(_thing != null) { _thing.Dispose(); _thing = null; } } 。。。我可以这样做: private Something _thing; void Dispose() { DiposeHelper.Dipose(ref _

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

我做了一个处置帮助者,所以不是这样:

private Something _thing;

void Dispose()
{
    if(_thing != null)
    {
        _thing.Dispose();
        _thing = null;
    }
}
。。。我可以这样做:

private Something _thing;

void Dispose()
{
    DiposeHelper.Dipose(ref _thing);
}
但显然我不能提供DisposeHelper。将IDisposable作为引用进行处理,除非我将某些内容转换为IDisposable,如:

private Something _thing;

void Dispose()
{
    IDisposable d = _thing;
    DiposeHelper.Dipose(ref d);
}
…这意味着它不会使原始字段无效

这里有一个更抽象的例子。这行得通,那不行:

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 { }

为什么我不能做呢?

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

然而,这是可行的:

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

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

我不知道你为什么不能这样做的技术原因

然而,这是可行的:

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

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

这不起作用,因为ref和out表达式的参数类型必须完全匹配。想象一下,如果DoThat真的有这样的实现:

private void DoThat(ref IFoo obj)
{
    obj = new SomeOtherImplementationOfFoo();
}
现在这个代码:

Something o = new Something();
DoThat(ref o);
最终将以o引用其他OO实现的实例,而不是某个东西——这显然是不对的


这就是为什么ref的工作方式是这样的——Rob的答案给出了一种解决方法。

它不起作用,因为ref和out表达式的参数类型必须精确匹配。想象一下,如果DoThat真的有这样的实现:

private void DoThat(ref IFoo obj)
{
    obj = new SomeOtherImplementationOfFoo();
}
现在这个代码:

Something o = new Something();
DoThat(ref o);
最终将以o引用其他OO实现的实例,而不是某个东西——这显然是不对的


这就是为什么ref的工作方式是这样的——Rob的答案给出了一种解决方法。

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

想象一下,您可以通过引用将派生as基传递到函数中。现在,该函数为参数指定一个新对象,该对象是基础对象,但不是派生对象。博姆

解决方法是使用Rob答案中的通用参数

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

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

想象一下,您可以通过引用将派生as基传递到函数中。现在,该函数为参数指定一个新对象,该对象是基础对象,但不是派生对象。博姆

解决方法是使用Rob答案中的通用参数

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