C# 如何从超类中调用两个子类的公共名称方法?
在日常工作中,我遇到了一个问题: 假设:C# 如何从超类中调用两个子类的公共名称方法?,c#,class,C#,Class,在日常工作中,我遇到了一个问题: 假设: 我们有一个对象a,它是object类型 A可能是类型B或类型C 类型B和C具有相同的名称方法GetSomething() 我们不知道B和C是否都实现了相同的接口(这意味着我们不知道它们之间的关系) 键入B和C继承自Object,这意味着没有任何帮助。除了相同的方法名称之外,我们对类型B和C一无所知 问题是,我想从A调用GetSomething,无论它是什么类型: //Object A maybe type B or C //both B and C ca
object
类型B
或类型C
B
和C
具有相同的名称方法GetSomething()
B
和C
是否都实现了相同的接口(这意味着我们不知道它们之间的关系)B
和C
继承自Object
,这意味着没有任何帮助。除了相同的方法名称之外,我们对类型B
和C
一无所知GetSomething
,无论它是什么类型:
//Object A maybe type B or C
//both B and C can call method
//but we just don't know type of A
var result=A.GetSomething();
如果您遇到这种情况,您会怎么做?这似乎需要一种抽象方法
public abstract class A {
protected abstract object GetSomething();
}
在每个派生类中,您需要实现GetSomething(),例如
然后,您可以在超类(A
)实现中的任意位置自由调用GetSomething()
)
如果您不想在超级类的实现中调用它,但在其他地方,您基本上有三种选择
- 更改超类的实现以包含方法的(潜在抽象)定义
- 使用动态类型
- 使用反射
设置为public
,而不是protected
)
第二和第三种选择都有同样的缺点。它们不是编译时类型的,所以在开发过程中,您可能(将)偶尔会出现运行时错误,而不是编译时错误。如果你有一个很高的测试覆盖率,这应该不是一个太大的问题
我更喜欢使用动态类型,因为它比反射版本更容易读写。假设GetSomething
返回一个int,它将如下所示
int result=((动态)A).GetSomething()
我已将结果更改为显式类型而不是隐式类型,因为否则它将被类型化为
dynamic
,导致任何涉及结果的表达式也被类型化为dynamic。如果您知道GetSomething
的返回类型,最好事先告诉编译器这似乎需要一个抽象方法
public abstract class A {
protected abstract object GetSomething();
}
在每个派生类中,您需要实现GetSomething(),例如
然后,您可以在超类(A
)实现中的任意位置自由调用GetSomething()
)
如果您不想在超级类的实现中调用它,但在其他地方,您基本上有三种选择
- 更改超类的实现以包含方法的(潜在抽象)定义
- 使用动态类型
- 使用反射
设置为public
,而不是protected
)
第二和第三种选择都有同样的缺点。它们不是编译时类型的,所以在开发过程中,您可能(将)偶尔会出现运行时错误,而不是编译时错误。如果你有一个很高的测试覆盖率,这应该不是一个太大的问题
我更喜欢使用动态类型,因为它比反射版本更容易读写。假设GetSomething
返回一个int,它将如下所示
int result=((动态)A).GetSomething()
我已将结果更改为显式类型而不是隐式类型,因为否则它将被类型化为
dynamic
,导致任何涉及结果的表达式也被类型化为dynamic。如果您知道GetSomething
的返回类型,那么最好事先告诉编译器如果A
没有该方法,那么您不应该考虑这样做,因为这是一种糟糕的设计,违反了OOP原则。但是,如果您必须这样做,您可以尝试使用反射:
MethodInfo methodInfo = this.GetType().GetMethod("GetSomething", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
if(methodInfo != null)
result = methodInfo.Invoke(this, new object[] {});
但是,我强烈建议您在
a
类中使用抽象类或默认的GetSomething()
。如果a
没有该方法,您不应该考虑这样做,因为这是一种糟糕的设计,违反了OOP原则。但是,如果您必须这样做,您可以尝试使用反射:
MethodInfo methodInfo = this.GetType().GetMethod("GetSomething", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
if(methodInfo != null)
result = methodInfo.Invoke(this, new object[] {});
但是,我强烈建议在a
类中使用抽象类或默认的GetSomething()
- 类型B和C具有相同的名称方法GetSomething()
- 我们不知道B和C是否都实现了相同的接口
interface IHasSomething
{
Something GetSomething();
}
var something = obj as IHasSomething
if (something != null)
{
var youWereLookingFor = something.GetSomething();
}
把它应用到B类和C类
假设您的B和C实例被声明为对象
,您可以尝试测试它们是否实现此接口:
interface IHasSomething
{
Something GetSomething();
}
var something = obj as IHasSomething
if (something != null)
{
var youWereLookingFor = something.GetSomething();
}
或者您可以尝试使用反射,这应该是与良好的OO设计相对应的最后手段(如果您想要添加参数和/或重载,调用另一个方法,使用不同的返回类型,等等)
- 类型B和C具有相同的名称方法GetSomething()
- 我们不知道B和C是否都实现了相同的接口
interface IHasSomething
{
Something GetSomething();
}
var something = obj as IHasSomething
if (something != null)
{
var youWereLookingFor = something.GetSomething();
}
把它应用到B类和C类
假设您的B和C实例被声明为对象
,您可以尝试测试它们是否实现此接口:
interface IHasSomething
{
Something GetSomething();
}
var something = obj as IHasSomething
if (something != null)
{
var youWereLookingFor = something.GetSomething();
}
或者你也可以尝试使用反射,作为最后的手段