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”用于编译时不可转换的类型。谢谢:)