web-dev-qa-db-ja.com

構造体の拡張メソッド

構造体に拡張メソッドを追加できますか?

34
Ghyath Serhal

はい、構造体に拡張メソッドを追加できます。拡張方法の定義に従って、簡単に実現できます。以下はintの拡張メソッドの例です

namespace ExtensionMethods
{
    public static class IntExtensions
     {
        public static bool IsGreaterEqualThan(this int i, int value)
        {
            return i >= value;
        }
    }
}
27
Pranay Rana

構造に拡張メソッドを追加することは可能ですが、重要な注意点があります。通常のstructメソッドメソッドはthisrefパラメーターとして受け入れますが、C#ではそれを行う拡張メソッドの定義を許可していません。 thisを変更するstructメソッドはやや危険である可能性があります(コンパイラーはstructメソッドを読み取り専用構造で呼び出すことを許可しますが、値によってthisを渡すため)、それらは時々適切なコンテキストでのみ使用されるように注意する場合に役立ちます。

ちなみに、vb.netでは、拡張メソッドがthisByRefパラメータとして受け入れることができます。これがクラス、構造体、または不明なカテゴリのジェネリックであるかどうかは関係ありません。これは、インターフェイスが構造によって実装される場合に役立ちます。たとえば、タイプList<string>.Enumeratorの変数を呼び出そうとすると、タイプIEnumerator<string>thisパラメータを受け取るか、値によってthisを受け取る拡張メソッドIEnumerator<string>に制限されたジェネリックのパラメーター。メソッドが列挙子を進めようとすると、メソッドが戻るときに、進めが取り消されます。ただし、参照によって制約付きジェネリックを使用する拡張メソッド(vb.netで可能)は、正常に動作します。

20
supercat

将来のGoogle社員(およびBingers)のために、構造体を拡張するためのコードをいくつか示します。この例では、値をdoubleタイプに変換します。

_public static class ExtensionMethods {

   public static double ToDouble<T>(this T value) where T : struct {
      return Convert.ToDouble(value);
   }
}
_

この後、ToDouble()を使用するのと同じようにToString()を使用できます。オーバーフローなどの変換項目には注意してください。

6
Paul

はい、構造体/値タイプで拡張メソッドを定義できます。ただし、参照型の拡張メソッドと同じ動作はありません。

たとえば、次のC#コードのGetA()拡張メソッドは、構造体への参照ではなく、構造体のcopyを受け取ります。つまり、構造体のC#拡張メソッドは元の構造体の内容を変更できません。

public static class TestStructExtensionMethods {
    public struct FooStruct {
        public int a;
    }
    public static int GetA(this FooStruct st) {
        return st.a;
    }
}

構造体の内容を変更するには、構造体パラメーターを「ref」として宣言する必要があります。ただし、「この参照」はC#では許可されていません。私たちができる最善のことは、次のような静的な非拡張メソッドです。

// this works, but is inefficient, because it copies the whole FooStruct
// just to return a
public static int GetA(ref FooStruct st) {
    return st.a;
}

VB.NETでは、これをByRef構造体拡張メソッドとして作成できるため、元の構造体を変更できます。

' This is efficient, because it is handed a reference to the struct
<Extension()> _ 
Public Sub GetA(ByRef [me] As FooStruct) As Integer
    Return [me].a
End Sub

' It is possible to change the struct fields, because we have a ref
<Extension()> _ 
Public Sub SetA(ByRef [me] As FooStruct, newval As Integer) 
    [me].a = newval
End Sub
3
David Jeske