一般に、拡張メソッドまたはカプセル化以外で 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
}