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

C#:有没有办法将类强制转换为它在运行时实现的接口,而不是编译时实现的接口?,c#,inheritance,interface,casting,type-safety,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 Derive

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

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
    }
}
我有一个不相关的类,它有一个基类字段:

public class UnrelatedClass
{
    public BaseClass foo;
}
假设我的实现假设foo应该是实现接口的某个派生类(但我不知道是哪一个,所以我不能直接转换到该类),我是否可以将它转换到IInterface并调用foo.SomeMethod(),而不生成编译错误


另外,我知道这是一种非常迂回的方法,应该只使用“IInterface foo”字段,但由于Unity没有序列化接口字段,也不想编写自定义检查器,所以我正在尝试这种解决方法。

您可以通过反射访问接口方法(慢!),或者您可以“安全”- 使用
as
操作符强制转换。如果强制转换失败,
as
运算符“返回”
null
。像这样:

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

您可以通过反射(慢!)或“安全”访问接口方法- 使用
as
操作符强制转换。如果强制转换失败,
as
运算符“返回”
null
。像这样:

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

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

abstract class BaseClassAndInterface: BaseClass, IInterface {
    public abstract void SomeMethod();
}
现在使
DerivedA
DerivedB
继承自
BaseClassAndInterface
,并在接口中实现该方法

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

现在,
foo
可以声明为
BaseClassAndInterface

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

abstract class BaseClassAndInterface: BaseClass, IInterface {
    public abstract void SomeMethod();
}
现在使
DerivedA
DerivedB
继承自
BaseClassAndInterface
,并在接口中实现该方法

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

现在,
foo
可以声明为
BaseClassAndInterface

现在您的
BaseClass
在您的设计中没有意义。如果您要稍微更改一下设计,那么您甚至可能不需要在运行时执行检查。下面是一个建议的设计,其中
基类
实现
i接口
,派生类需要覆盖它:

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

现在您的
基类
在您的设计中没有任何意义。如果您要稍微更改一下设计,那么您甚至可能不需要在运行时执行检查。下面是一个建议的设计,其中
基类
实现
i接口
,派生类需要覆盖它:

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

BaseClass
没有
SomeMethod
IInterface
拥有它,那么为什么不能将
SomeMethod
放在
BaseClass
中,例如
abstract
?为什么
BaseClass
不实现
IInterface
?使用
is
关键字检查:
如果(foo is IInterface){…}
您的继承设计可能确实存在问题。您试图实现的正是接口的用途。您可以使用反射,但我强烈建议在这种情况下不要使用反射(它会减慢您的解决方案)。您不能将UnrelatedClass.foo声明为一个接口吗?或者让基类实现接口?
BaseClass
没有
SomeMethod
IInterface
拥有它,那么为什么不能将
SomeMethod
放在
BaseClass
中,例如
abstract
?为什么
BaseClass
不实现
IInterface
?使用
is
关键字检查:
如果(foo is IInterface){…}
您的继承设计可能确实存在问题。您试图实现的正是接口的用途。您可以使用反射,但我强烈建议在这种情况下不要使用反射(它会减慢您的解决方案)。您不能将UnrelatedClass.foo声明为一个接口吗?或者让BaseCLASS实现IOffice?我想到了这一点——它适用于我给出的具体示例,但是如果您想使用不同的基类来实现I接口(因为在每个中间都需要一个抽象基类),则会崩溃。事实上,我为我的原始问题(在对象之间传递冲突)找到了一个不同的解决方法,但从一个假设的角度来看,我仍然对这个问题感兴趣:我可以使用在运行时实现它们的对象的接口成员吗,但是这个变量在编译时不是吗?我想到了这一点——它适用于我所给出的具体例子,但是如果你想使用不同的基类来实现I接口(因为它们中间需要一个抽象的基类,那么它们就崩溃了)。事实上,我为我的原始问题(在对象之间传递冲突)找到了一个不同的解决方法,但从一个假设的角度来看,我仍然对这个问题感兴趣:我可以使用一个在运行时实现它们的对象中的接口成员,但该变量在编译时不实现它们吗?很好!有一阵子我忘了这个问题,但这正是我想要的。我不知道可以将“as”用于编译时不可转换的类型。谢谢:)很好!有一阵子我忘了这个问题,但这正是我想要的。我不知道可以将“as”用于编译时不可转换的类型。谢谢:)