2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

.NET 8におけるextern

Last updated at Posted at 2024-02-08

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);

実行結果:
alt 画像

.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の方式の性能を比較したものです。やはり、性能はずっと優れています。

alt 画像

(Translated by GPT)

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?