Adding functionality to C # structs

I am trying to find how to add functionality to C # structs, and in a more elegant way than just wrap them in completely new classes. An extension method is simply not as efficient as an override, and certainly cannot provide a way to handle struct event events.

The specific problem I am currently facing is detecting and responding to changes in the members of the Vector2 structure. This is only an internal requirement, so users of my library should be able to use / perceive only Vector2 structures when interacting with it (while still setting internal events).


Generally, how can I extend C # structs other than extension or encapsulation methods?

Specifically, how can I extend the Vector2 framework to support firing / handling events?

0


source to share


1 answer


Generally, how can I extend C # structs other than extension methods or encapsulation?

The only way is to create extension methods or use encapsulation.

Specifically, how can I extend the Vector2 structure to support firing / processing events?

As I said earlier, you can use encapsulation and create a class . So use this code:

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);
    }
}

      

Then you can add interfaces, methods and events.

EDIT:

But how would you tell if X or Y is changing? Tell the user to "get" the Vector and then set one of its members (X or Y). I can add a firing event when the entire vector is set, but not when one of its participants is set after "get". Keep in mind that I don't want to force the user to use the new vector class to interact with my library. I don't even want him / her to know that the new vector class is being used internally.



First, if you want to completely mask that the type structure is being used internally Vector2

, you should rewrite all methods like this:

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);
    }
}

      

For more information see here .

Now it's easy if you want to create an event that fires when some members change. I would create costumized EventArgs. Let the code be written:

//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;
    }
}

      

Then you can write your own event:

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
}

      

+2


source







All Articles