externは、C#で外部のアセンブリに含まれる関数やメソッドを参照するために使用されるキーワードです。通常、externは非マネージコード(例えば、C/C++で書かれたDLL)との連携に用いられ、C#のコード内で非マネージコードの 関数を呼び出すために使用されます。
MessageBox(IntPtr.Zero, "Hello, extern!", "Info", 0);
[DllImport("user32.dll")] static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
.NET 8では、externの使用が拡張され、UnsafeAccessorを使って.NETで書かれたDLLを簡単に呼び出すことができます。
using System.Runtime.CompilerServices; using System.Runtime.InteropServices;
var test = new TestClass();
Console.WriteLine(GetTime(test)); //プライベートメソッドの呼び出し
Console.WriteLine(GetNo(test)); //プライベートフィールドの読み込み
GetNo(test) = 20; //プライベートフィールドへの割り当て
Console.WriteLine(GetNo(test));
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GetTime")] static extern DateTime GetTime(TestClass test);
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_no")] static extern ref int GetNo(TestClass test);
public class TestClass
{
int _no = 10;
DateTime GetTime()
{
return DateTime.Now;
}
}
現在、UnsafeAccessorKindがサポートするタイプは以下の通りです:
namespace System.Runtime.CompilerServices
{
public enum UnsafeAccessorKind
{
Constructor = 0,
Method = 1,
StaticMethod = 2,
Field = 3,
StaticField = 4
}
}
この機能は、一見するとリフレクションに似ていますが、リフレクションよりも単純で、シグネチャのマーキングだけでよいです。
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using static System.Net.Mime.MediaTypeNames;
BenchmarkRunner.Run<Test>();
public class Test
{
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GetTime")] public static extern DateTime GetTime(TestClass test);
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_no")] public static extern ref int GetNo(TestClass test);
[Benchmark]
public void UnsafeTest()
{
var test = new TestClass();
var t = GetTime(test);
}
[Benchmark]
public void RefTest()
{
var test = new TestClass();
var type = test.GetType();
var method = type.GetMethod("GetTime", BindingFlags.NonPublic | BindingFlags.Instance);
var t = method?.Invoke(test, new object[0]);
}
}
public class TestClass
{
int _no = 10;
DateTime GetTime()
{
return DateTime.Now;
}
}
以下は、BechamrkDotNetを使用してリフレクションとUnsafeAccessorの方式の性能を比較したものです。やはり、性能はずっと優れています。
(Translated by GPT)