我可以有一个接口参数,通过引用传递?

时间:2015-03-26 00:12:21

标签: c# interface pass-by-reference

我有一个带有此签名的方法:

protected bool MyMethod (ref IMyInterface model) {
    // stuff and things
}

我有一个模型,我从这个班级传入:

public class MyClass: IMyInterface {
    // class stuff and things
}

我试图将我的模型传递给方法,如下所示:

var model = new MyClass():

MyMethod(ref model);

但是,我收到有关与参数类型不匹配的类型的错误。如果我不通过引用传递,它可以正常工作。或者,如果我投射它并像这样传递它,它工作正常。

var tempModel = (IMyInterface)model;

MyMethod(ref tempModel);
如果没有必要,我宁可避免演员表,但如果没有它,我也无法通过。我想如果类实现了接口,我可以传递模型。这不是我可以通过参考做的事情,还是我错过了什么?

3 个答案:

答案 0 :(得分:14)

如果您不使用隐式类型,只需将变量定义为接口,它就会起作用:

IMyInterface model = new MyClass():

MyMethod(ref model);

ref传递的参数必须与该类型完全匹配,因为它们可以在方法中重新分配给与该合同匹配的另一种类型。在你的情况下,这不会起作用。想象一下:

protected bool MyMethod (ref IMyInterface model) 
{
    // This has to be allowed
    model = new SomeOtherMyInterface();
}

// Now, in your usage:
var model = new MyClass(); // Exactly the same as MyClass model = new MyClass();

MyMethod(ref model); // Won't compile...

// Here, model would be defined as `MyClass` but have been assigned to a `SomeOtherMyInterface`, hence it's invalid...

答案 1 :(得分:5)

ref无法获取所请求类型的子类型(即。IMyInterface),因为该方法无法保证分配不会违反调用方(即它需要一个MyClass)。因此,使用ref(或out)需要完全类型。

这实际上是错误:

MyClass m = new MyClass();
IMyInterface f = m; // Okay: "m is IMyInterface"

MyMethod(ref f);    // Okay
m = f;              // Illegal: can't guarantee "f is MyClass".

C#只是禁止使用ref,但有一点" help"手动..

m = (MyClass)f;     // "Trusting this is okay"

请参阅https://stackoverflow.com/a/2877515/2864740有关out参数关键字的差异规则原因的更深入说明。

答案 2 :(得分:3)

你可以通过这样的泛型实现这一点:

public static class Disposable
{
    public static void TryDisposeAndClear<T>(ref T obj) where T : IDisposable
    {
        try
        {
            obj.Dispose();
        }
        catch { }

        obj = default(T);
    }
}