C#:有没有办法将类强制转换为它在运行时实现的接口,但不是编译时间?

时间:2017-10-01 13:11:42

标签: c# inheritance interface casting type-safety

如果我有一个基类和几个实现接口的派生类,例如:

public class BaseClass
{

}

public interface IInterface
{
    void SomeMethod();
}

public class DerivedA : BaseClass, IInterface
{
    public void SomeMethod()
    {
        // some implementation
    }
}
public class DerivedB: BaseClass, IInterface
{
    public void SomeMethod()
    {
        // some other implementation
    }
}

我有一个不相关的类,它有一个BaseClass字段:

public class UnrelatedClass
{
    public BaseClass foo;
}

如果我的实现假设foo应该是一些实现接口的派生类(但我不知道哪个,所以我不能只是强制转换为该类),我可以以某种方式将其转换为IInterface并调用foo.SomeMethod ()没有生成编译错误?

PS-我知道这是一种非常迂回的方式,而且应该只使用“IInterface foo”字段,但由于Unity没有序列化接口字段而不想编写自定义检查器 - 这是一种解决方法我我正在努力。

3 个答案:

答案 0 :(得分:4)

你可以通过反射访问界面方法(慢!)或者你可以安全地 - 投'使用as运算符。 as运算符'返回' null如果演员表失败。像这样:

var impl = foo as IInterface;
impl?.SomeMethod()
// or if(impl != null) impl.SomeMethod();

答案 1 :(得分:1)

现在你的BaseClass对你的设计毫无意义。如果你稍微改变你的设计,那么你甚至可能不需要在运行时执行检查。这是一个提议的设计,其中BaseClass实现IInterface,派生类需要覆盖它:

public interface IInterface
{
    void SomeMethod();
}

public abstract class BaseClass : IInterface
{
    public abstract void SomeMethod();
    // Or virtual with common implementation
}

public class DerivedA : BaseClass
{
    public override void SomeMethod()
    {
        // some implementation
    }
}
public class DerivedB : BaseClass
{
    public override void SomeMethod()
    {
        // some other implementation
    }
}

答案 2 :(得分:0)

我将通过改变您的设计来提供解决方案。我想您的最终目标是希望foo对象拥有BaseClass IInterface的所有成员。你可以像这样创建一个抽象类:

abstract class BaseClassAndInterface: BaseClass, IInterface {
    public abstract void SomeMethod();
}

现在让DerivedADerivedB继承自BaseClassAndInterface并在界面中实现该方法。

public class DerivedA : BaseClassAndInterface
{
    public override void SomeMethod()
    {
        // some implementation
    }
}
public class DerivedB: BaseClassAndInterface
{
    public override void SomeMethod()
    {
        // some other implementation
    }
}

现在,foo可以声明为BaseClassAndInterface