0

我正在试图找到如何将功能添加到C#结构中,并且以比将它们包装在全新类中更优雅的方式。扩展方法不如覆盖强大,并且绝对不能提供结构事件触发/处理功能。为C#结构添加功能

我目前面临的具体问题是检测并对Vector2结构成员中的更改作出反应。这只是一个内部要求,所以我的图书馆的用户应该能够在与其交互时使用/感知Vector2结构(同时仍然引发内部事件)。


一般来说,我可以如何扩展C#的结构以外由扩展方法或封装?

具体来说,我该如何扩展Vector2结构以支持事件触发/处理?

+14

我会说你需要一个类,而不是一个结构 – devundef

+1

就像devundef说。 C#中的结构只不过是将相关数据放在一起的轻量级方式。如果你需要更多的逻辑和可扩展性,然后使用类。 – Euphoric

+0

@Euphoric:你为什么说C#中的结构是“仅仅是保持相关数据在一起的轻量级方式”?确实,一个结构不能继承另一个结构,但是你可以在结构上有方法。你为什么说他们是“轻量级”? –

回答

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的变化?假设用户“获取”矢量,然后设置其中一个成员(X或Y)。我可以添加事件 当Vector设置为整体时触发,但不是当其中一个 成员设置在'get'后面时。请记住,我不想强​​制 用户使用新的矢量类以便与我的 库进行交互。我甚至不希望他/她必须知道内部使用了一个新的矢量类 。

首先,如果你想使用类型的结构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); 
    } 
} 

欲了解更多信息look here

现在很简单,如果你想创建一个成员更改时触发的事件。 我会创建一个costumized的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 
} 
+0

但是,我会如何检测X或Y是否发生了变化?假设用户“获取”Vector,然后设置其中一个成员(X或Y)。我可以在Vector的整体设置时添加事件触发,但不能在“get”之后设置其中的一个成员。请记住,我不想强​​制用户使用新的矢量类来与我的库进行交互。我甚至不希望他/她必须知道内部使用了一个新的矢量类。 – Griffin

+0

好的,我编辑了我的答案。 –

+1

我的编辑能帮助你吗? –