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

Can I have an interface parameter, pass by reference?

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

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

我有一个从这个 class 传入的模型:

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

我正在尝试将我的模型传递到方法中,如下所示:

var model = new MyClass():

MyMethod(ref model);

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

var tempModel = (IMyInterface)model;

MyMethod(ref tempModel);

如果没有必要,我宁愿避免强制转换,但没有它我无法通过。我想如果 class 实现了接口,我可以通过模型。这不是我可以通过参考做的事情还是我遗漏了什么?

ref 不能采用所请求类型的 子类型 (即 IMyInterface),因为这样该方法就不能保证赋值不会违反调用者(即它想要 MyClass)。因此使用 ref(或 out)需要 exact 类型。

这实际上是错误所在:

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"

请参阅 更深入地解释 out 参数关键字的变化规则的原因。

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

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...

您可以像这样使用泛型实现此目的:

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

        obj = default(T);
    }
}