外部如何在C#中工作?

时间:2011-02-24 21:30:09

标签: c# .net performance extern modifier

每当我深入了解反射器时,我都会碰到没有光源的extern方法。我在http://msdn.microsoft.com/en-us/library/e59b22c5(v=vs.80).aspx阅读了msdn文档。我从那篇文章得到的是必须注入带有extern修饰符的方法。我将其解释为意味着它的工作方式类似于抽象工厂模式。我也注意到我从未见过非静态的外部方法。静态声明是一个要求(我可以看到这有什么意义)?我还在猜这里,我不确定它是如何运作的。在我看来,编译器必须识别某些缓解处理的属性,但我不知道除了我遇到的属性之外的属性,如MSDN示例中的MethodImplAttributeDllImportAttribute。有人如何利用extern属性?它说,在许多情况下,这可以提高性能。另外,我如何查看extern方法的来源Object.InternalGetEquals()

4 个答案:

答案 0 :(得分:95)

考虑阅读C#规范的第10.6.7节,它解答了许多问题。为了您的方便,我在这里复制了部分内容:


  

当方法声明包含时   extern修饰符,那个方法说   成为一种外部方法。外部   方法在外部实施,   通常使用除以外的语言   C#。因为外部方法   声明不提供实际   实现,方法体   外部方法只包含一个   分号。外部方法可能不会   是通用的。外部修饰符是   通常与a结合使用   DllImport属性,   允许外部方法   由DLL实现(动态链接   库)。执行环境   可以支持其他机制   外部方法的实现   可以提供。当一个外部   方法包括DllImport属性,   方法声明也必须   包括一个静态修饰符。


  

有人如何利用extern属性?

  • 使用您选择的非托管语言编写代码。
  • 将其编译为DLL,导出代码的入口点。
  • 创建一个互操作库,将该方法定义为给定DLL中的extern方法。
  • 从C#中调用它。
  • 利润!
  

如何查看Object.InternalGetEquals()等外部方法的来源?

转到https://github.com/dotnet/coreclr/tree/master/src/vm

答案 1 :(得分:29)

标有extern [DllImport]属性的方法通常是对C库的调用。此功能对于调用WinAPI或遗留代码非常有用。

这是来自MSDN的示例:

using System;
using System.Runtime.InteropServices;
class MainClass 
{
   [DllImport("User32.dll")]
   public static extern int MessageBox(int h, string m, string c, int type);

   static int Main() 
   {
      string myString; 
      Console.Write("Enter your message: ");
      myString = Console.ReadLine();
      return MessageBox(0, myString, "My Message Box", 0);
   }
}

它调用MessageBox,它在Windows user32.dll库中定义。运行时在这里为您完成所有繁重的工作,尽管有时您需要手动管理内存。如果您的签名错误,您的程序可能会失败,您可能会引入泄漏或方法可能返回完全不同的东西,所以要小心!我发现pinvoke.net是纠正不同API签名的绝佳工具。

.NET Framework中的一些extern方法没有[DllImport]属性,但是用[MethodImpl (MethodImplOptions.InternalCall)]属性修饰,通常是在CLR中实现的,用C语言编写同样。有些此类方法无法在C#中实现,因为它们管理运行时本身,有些是在C中实现的,因为它们的性能至关重要且C更快。

这就是关于他们的MSDN says

  

指定内部呼叫。内部调用是对在公共语言运行库本身内实现的方法的调用。

至于查看实际的实现代码,我怀疑你是否可以从Microsoft获得它,但有some cool alternative implementations of CLR around所以一定要检查它们。

答案 2 :(得分:3)

extern使用平台调用(pinvoke)来促进托管程序集调用非托管代码。 extern关键字通知编译器它需要生成正确的代码以允许正确的数据封送。

答案 3 :(得分:2)

我们使用" extern"方法声明中的修饰符。它用于指示该方法是在外部实现的。 "的常见用途extern"修饰符具有DllImport属性。使用此属性管理非C#函数调用。 如果您使用的是extern修饰符,则必须包含以下命名空间:

using System.Runtime.InteropServices;

语法类似于:

[DllImport("User32.dll")] public static extern int MessageBox(int h, string m, string c, int type);