Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过继承确定两个MethodInfo实例是否表示相同的(非虚拟)方法_C#_.net_Inheritance_Reflection_Methodinfo - Fatal编程技术网

C# 通过继承确定两个MethodInfo实例是否表示相同的(非虚拟)方法

C# 通过继承确定两个MethodInfo实例是否表示相同的(非虚拟)方法,c#,.net,inheritance,reflection,methodinfo,C#,.net,Inheritance,Reflection,Methodinfo,首先我给出一个简单的例子,我知道答案。考虑: class Animal { public virtual void M() { Console.WriteLine("a"); } } class Giraffe : Animal { public override void M() { Console.WriteLine("g"); } } 然后在代码的某个地方: var am = typeof(Animal).GetMethod("M"); var gm = typeof(G

首先我给出一个简单的例子,我知道答案。考虑:

class Animal
{
  public virtual void M() { Console.WriteLine("a"); }
}
class Giraffe : Animal
{
  public override void M() { Console.WriteLine("g"); }
}
然后在代码的某个地方:

  var am = typeof(Animal).GetMethod("M");
  var gm = typeof(Giraffe).GetMethod("M");
  Console.WriteLine(am == gm);  // False
  Console.WriteLine(am == gm.GetBaseDefinition());  // True
我们看到,
am
gm
被认为是不平等的,这是完全公平的(后者是前者的替代)。然而,通过最后一行,我们可以确定这两种方法是相关的;一个是另一个的“基本方法”

(您甚至可以检查引用的相等性,
(object)am==(object)gm.GetBaseDefinition()
,您仍然可以得到True。)

现在我有一个问题要问。考虑一下:

class Plant
{
  public void N() /* non-virtual */ { }
}
class Tree : Plant
{
}
与:

在这种情况下,
pn
tn
仍然被认为是不同的(它们的
反射类型不同)

如何测试它们是否实际上(通过继承)是相同的方法


框架中有内置的方法吗?如果我必须手工解决这个问题,策略是什么?我必须检查两者是否具有相同的
DeclaringType
,是否具有相同的(类型)参数列表,是否具有相同数量的类型参数?

您可以使用
DeclaringType
属性:

am.DeclaringType.Dump(); // Animal
gm.DeclaringType.Dump(); // Giraffe

pn.DeclaringType.Dump(); // Plant
tn.DeclaringType.Dump(); // Plant
或者您可以使用
MethodHandle

(am.MethodHandle == gm.MethodHandle).Dump(); // False

(pn.MethodHandle == tn.MethodHandle).Dump(); // True
虽然我不确定这是否完全可靠

如果您只关心该方法是否在给定类型中被实际重写,那么还可以使用
BindingFlags

var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;

typeof(Plant).GetMethod("N", flags).Dump(); // N
typeof(Tree).GetMethod("N", flags).Dump(); // null

DeclaringType
对于在不同名称空间中声明了相同名称的两个不同类是否相同?如果是,您可能会认为一个类是另一个的基类,而实际上基类具有相同的名称,并且位于其他地方。@Kapol
DeclaringType
不是
字符串,而是
类型
-它不是按名称比较的,而是按类型ID比较的。@Kapol事实上,依赖名称是一个坏主意,原因不止于此——例如,在CLI中,使用具有不同名称的方法重写方法是完全有效的。C#只在显式接口实现IIRC中使用它,但CLI上的其他语言也可能用于其他情况(当然,在IL中它是完全免费的)。感谢您的评论。我已经知道了
DeclaringType
(在问题的最后一部分提到)。但是
MethodHandle
似乎解决了这个问题。将此答案标记为已接受。
var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;

typeof(Plant).GetMethod("N", flags).Dump(); // N
typeof(Tree).GetMethod("N", flags).Dump(); // null