0

私は、C# 構造に機能を追加する方法を見つけようとしていますが、完全に新しいクラスでラップするよりも洗練された方法で行います。拡張メソッドはオーバーライドほど強力ではなく、構造体イベントの起動/処理機能を提供することもできません。

ただし、私が現在直面している特定の問題は、Vector2 構造体のメンバーの変更を検出して対応することです。ただし、これは内部要件にすぎないため、私のライブラリのユーザーは、(内部イベントを開始しながら) 対話するときに Vector2 構造のみを使用/認識できる必要があります。


一般に、拡張メソッドまたはカプセル化以外で C# 構造を拡張するにはどうすればよいですか?

具体的には、Vector2 構造を拡張してイベントの発生/処理をサポートするにはどうすればよいですか?

4

1 に答える 1

2

一般に、拡張メソッドまたはカプセル化以外で C# 構造を拡張するにはどうすればよいですか?

唯一の方法は、拡張メソッドを作成するか、カプセル化を使用することです。

具体的には、Vector2 構造を拡張してイベントの発生/処理をサポートするにはどうすればよいですか?

前に述べたように、カプセル化を使用してクラスを作成できます。したがって、次のコードを使用します。

public class ExtendedVector2 {
    public Vector2 Vector{
        get;
        private set;
    }

    public ExtendedVector2(float value){
        Vector = new Vector2(value);
    }   

    public ExtendedVector2(float x, float y){
        Vector = new Vector2(x, y);
    }
}

次に、インターフェイス、メソッド、およびイベントを追加できます。

編集 :

しかし、X または Y が変更されたかどうかをどのように検出しますか? ユーザーがベクターを「取得」し、そのメンバーの 1 つ (X または Y) を設定するとします。ベクター全体が設定されたときに発生するイベントを追加できますが、「get」の後にそのメンバーの 1 つが設定されたときはできません。ライブラリを操作するために、ユーザーに新しいベクター クラスの使用を強制したくないことに注意してください。新しいベクタークラスが内部で使用されていることを彼/彼女に知られたくありません。

まず、型の構造体が内部で使用されていることを完全にマスクしたい場合は、Vector2すべてのメソッドを次のように書き換える必要があります。

public class ExtendedVector2 {
    //...
    private Vector2 _vector2;  

    //mask X and Y values of Vector2 structure 
    public float X{
        set{ _vector2.X = value; }
        get{ return _vector2.X; }
    }

    public float Y{
        set{ _vector2.Y = value; }
        get{ return _vector2.Y; }
    } 

    //example to mask a method of Vector2 structure 
    public static float Dot(ExtendedVector2 value1, ExtendedVector2 value2){
        return Vector.Dot(value1, value2);
    }

    //override the cast to Vector2
    public static implicit operator Vector2(ExtendedVector2 value) //I'd make it implicit because I'd think to it like an upcast
    {
        return new Vector2(value.X, value.Y);
    }
}

詳細については、こちらをご覧ください

1 つのメンバーが変更されたときに発生するイベントを作成するのは簡単です。コスチューム化された EventArgs を作成します。いくつかのコードを書きましょう:

//use the convention of eventName+EventArgs
class MemberChangedEventArgs : EventArgs
{
    public readonly float LastValue{
        get;
        set;
    }
    public readonly float NewValue{
        get;
        set;
    }

    public MemberChangedEventArgs(float LastValue, float NewValue)
    {
        this.LastValue = LastValue;
        this.NewValue = NewValue;
    }
}

次に、独自のイベントを作成できます。

public class ExtendedVector2 {
    private Vector2 _vector2;  

    public float X{
         set{                  
             if(_vector2.X != value)           
               OnMemberXChanged(new MemberChangedEventArgs(_vector2.X, value));

             _vector2.X = value;   
         }
         get{ return _vector2.X; }
    }

    public float Y{
         set{ 
             if(_vector2.Y != value)
               OnMemberYChanged(new MemberChangedEventArgs(_vector2.Y, value));

             _vector2.Y = value;                    
         }
         get{ return _vector2.Y; }
    }        

    public event EventHandler<MemberChangedEventArgs> MemberXChanged;
    public event EventHandler<MemberChangedEventArgs> MemberYChanged;

    public ExtendedVector2(float value){
        Vector = new Vector2(value);
    }   

    public ExtendedVector2(float x, float y){
        Vector = new Vector2(x, y);
    }

    private virtual void OnMemberXChanged(MemberChangedEventArgs e){
        if(MemberXChanged != null)
           MemberXChanged(this, e);
    }

    private virtual void OnMemberYChanged(MemberChangedEventArgs e){
        if(MemberYChanged != null)
           MemberYChanged(this, e);
    }
    //... 

    //here mask the Vector2 structure using the previous solution
}
于 2012-08-29T09:10:59.517 に答える