我正在試圖找到如何將功能添加到C#結構中,並且以比將它們包裝在全新類中更優雅的方式。擴展方法不如覆蓋強大,並且絕對不能提供結構事件觸發/處理功能。爲C#結構添加功能
我目前面臨的具體問題是檢測並對Vector2結構成員中的更改作出反應。這只是一個內部要求,所以我的圖書館的用戶應該能夠在與其交互時使用/感知Vector2結構(同時仍然引發內部事件)。
一般來說,我可以如何擴展C#的結構以外由擴展方法或封裝?
具體來說,我該如何擴展Vector2結構以支持事件觸發/處理?
我正在試圖找到如何將功能添加到C#結構中,並且以比將它們包裝在全新類中更優雅的方式。擴展方法不如覆蓋強大,並且絕對不能提供結構事件觸發/處理功能。爲C#結構添加功能
我目前面臨的具體問題是檢測並對Vector2結構成員中的更改作出反應。這只是一個內部要求,所以我的圖書館的用戶應該能夠在與其交互時使用/感知Vector2結構(同時仍然引發內部事件)。
一般來說,我可以如何擴展C#的結構以外由擴展方法或封裝?
具體來說,我該如何擴展Vector2結構以支持事件觸發/處理?
一般情況下,如何擴展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
}
但是,我會如何檢測X或Y是否發生了變化?假設用戶「獲取」Vector,然後設置其中一個成員(X或Y)。我可以在Vector的整體設置時添加事件觸發,但不能在「get」之後設置其中的一個成員。請記住,我不想強制用戶使用新的矢量類來與我的庫進行交互。我甚至不希望他/她必須知道內部使用了一個新的矢量類。 – Griffin
好的,我編輯了我的答案。 –
我的編輯能幫助你嗎? –
我會說你需要一個類,而不是一個結構 – devundef
就像devundef說。 C#中的結構只不過是將相關數據放在一起的輕量級方式。如果你需要更多的邏輯和可擴展性,然後使用類。 – Euphoric
@Euphoric:你爲什麼說C#中的結構是「僅僅是保持相關數據在一起的輕量級方式」?確實,一個結構不能繼承另一個結構,但是你可以在結構上有方法。你爲什麼說他們是「輕量級」? –