【问题标题】:What's the type of "Method" itself in C#?C# 中“方法”本身的类型是什么?
【发布时间】:2018-07-20 11:34:29
【问题描述】:

听说C#是一种纯面向对象的编程语言,因为所有的东西都源自System.Object

所以我怀疑方法本身的 type 是什么。我尝试使用StackTraceStackFrame 来获取方法的类型,但我只得到了类的名称,即声明了哪些方法。

当然,我试过这个:

var func = new TestClass().TestMethod; //TestMethod is a method of TestClass

但是我只得到了这个错误。

CS0815    Cannot assign method group to an implicitly-typed variable 

方法可以分配给Func<..., TResult>typed 变量。我用 Func 和返回字符串的方法进行了测试,然后我得到了这个:

// Result of
// Func<string> func = new TestClass().TestMethod;
// func.GetType();
Instance TestClass -> TestMethod Type : System.Func`1[System.String]

但它的类型名是Func&lt;string&gt;。那么,方法的真正类型名是什么?

编辑 2018 年 2 月 10 日上午 1:46,KST(格林威治标准时间 +09:00)

好吧,我总结一下。函数本身没有类型,也不是对象,Delegate / Func&lt;&gt; 只是 .NET Framework 的一个特性,可以作为一等公民处理函数(但它不是 FCC )。对吗?

【问题讨论】:

  • 你可能在原生 C++ 中很常见,它可能将返回类型 T 的任何函数分配给 T 上的任何指针。然后像这样调用它。好吧,.NET Framework 设计团队竭尽全力,因此您永远不必处理裸指针。代表只是这些替代品之一。我个人觉得这种方式更好,因为编译器可以检查你所做的事情是否有意义。
  • 方法不是对象,因此它没有类型。 C# 中的方法是将函数附加到类的面向对象的方式,但它们不像 JavaScript 中的函数那样是一等公民。

标签: c# types


【解决方案1】:

方法没有类型。方法就是它们的本质——只是对象或类上的“可调用函数”。您可以将它们分配给具有相同签名的DelegatesFunc,这只是框架的一个功能,但方法本身没有任何“类型”。

最接近类型的可能是方法的返回值(如果有的话)。

【讨论】:

  • 你能看看我的总结吗?它在问题的末尾。
  • Delegate types 和 Func&lt;...&gt; 实际上是类型。但是方法本身没有类型,尽管当方法签名与委托签名匹配时,它们可以表示这些类型的“实例”。
【解决方案2】:

方法不是对象,因此它没有类型。

C# 中的方法是将函数附加到类的面向对象的方式,但它们不像 JavaScript 中的函数那样是一等公民。

这就是为什么不能将方法分配给变量的原因。

你不能这样做:

var func = Int32.Parse;

但是你可以这样做:

Func<string, int> func2 = Int32.Parse;

在第二个示例中,尽管看起来您实际上是在将方法分配给变量,但实际情况是编译器创建了一个 Func&lt;string, int&gt; 的新实例,它是一个委托(最终派生自 System.Object ) 恰好实际上持有对方法本身的类型安全引用。

那个委托一个对象,可以被赋值并作为参数传递给其他方法,但它不是方法本身,而是一个包装器。

【讨论】:

  • 有趣的是,您在一句话中说我们不能将方法分配给变量,只是为了将方法分配给文本的下一行中的变量。我看不出编译器如何创建一个委托(变量)的新实例,然后将其分配给方法指针,可以将其表述为“这不是将方法分配给变量”——这实际上就是你正在做的事情.将对象引用(或这种意义上的指针)分配给变量和将函数指针分配给变量有什么区别?
  • Delegate 对象不是方法指针,而是类的实例。正如我之前所说,方法不是对象,因此不能分配给变量。 func 是编译器创建的匿名类型的对象。您可以使用 dotPeek 或类似的反编译器工具来实际查看编译器为您创建的内容。
  • 委托是一个用于引用方法的类 - 并且将方法指针保存在委托中。另外,这与将对象引用分配给变量有何不同?编译器为将方法分配给委托变量所做的工作不会改变它正在将方法分配给变量的事实(以确切的语义方式,因为对象引用不是类指针,但使用了它的指针由编译器/CLR 在后台引用自身)。
【解决方案3】:

所有事物都派生自 System.Object,但并非所有事物都是事物。

Object.GetType() 解释:

“由于 System.Object 是 .NET Framework 类型系统中所有类型的基类,因此可以使用 GetType 方法返回代表所有 .NET Framework 类型的 Type 对象。.NET Framework 识别以下五个类别类型:

类,派生自 System.Object,

值类型,派生自 System.ValueType。

从 .NET Framework 2.0 开始的 System.Object 派生的接口。

枚举,派生自 System.Enum。

委托,派生自 System.MulticastDelegate。"

实例方法不是其中之一,除了它的类之外它没有任何意义。

【讨论】:

  • 接口不派生任何东西。试试这个:typeof(System.Collections.IEnumerable).BaseType 它返回 null
  • 因此,虽然您对 BaseType 的看法是正确的,但您可以执行 typeof(System.Collections.IEnumerable).ToString() 或 typeof(System.Collections.IEnumerable).GetHashCode() 并获得预期的结果。如果您允许规范胜过现实生活,也许这是一个错误而不是正确的行为:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-13
  • 2023-01-22
  • 1970-01-01
  • 2013-05-27
  • 2017-11-03
  • 2018-04-22
  • 2016-03-10
相关资源
最近更新 更多