1

Not sure how to word this or search for it as I lack the "real name" for this.

Certain structs in C# can be used directly as their containing type, take Nullable<> for instance, a Nullable can directly be treated as an int, for example:

Nullable<int> ex;

void Example(){
    ex += 1;
}

My question is now to implement this kind of behaviour in my own structs, for example I could make a Savable and still be able to treat the variable like a normal int like in nullable? instead of doing mySavable.value, for example.

Hope my question is clear enough, it's without a doubt a duplicate question, but I could not find another in my searches as I'm lacking the proper name of this "technique". So sorry in advance for that!

Thanks very much!

beau c
  • 93
  • 1
  • 9

2 Answers2

4

The Nullable<> type is a bad example. It is compiler supported, and it does magic that no one else can do.

You can define some implicit/explicit cast operators, that will convert YourStruct <-> int implicitly or explicitly, or you can define some operators that accept for example YourStruct + int. Both solutions will solve your question. Note that to obtain the += operator you only need to define the + operator that returns a YourStruct (or define an implicit conversion int -> YourStruct).

For example, overloading the operator+(Example1, Example1) and overloading the implicit cast conversion from/to int you could:

public struct Example1
{
    public readonly int Value;

    public Example1(int value)
    {
        this.Value = value;
    }

    public static Example1 operator +(Example1 t1, Example1 t2)
    {
        return new Example1(t1.Value + t2.Value);
    }

    // This is used only for the "int v1 = e1;" row
    public static implicit operator int(Example1 value)
    {
        return value.Value;
    }

    public static implicit operator Example1(int value)
    {
        return new Example1(value);
    }
}

and then

Example1 e1 = 1;
Example1 e2 = 2;
Example1 sum1 = e1 + e2;
Example1 sum2 = e1 + 4;
Example1 sum3 = 4 + e1;
sum3 += sum1;
sum3 += 1;
int v1 = e1;

Or you could simply overload the various operator+ between Example2 and int:

public struct Example2
{
    public readonly int Value;

    public Example2(int value)
    {
        this.Value = value;
    }

    public static Example2 operator +(Example2 t1, Example2 t2)
    {
        return new Example2(t1.Value + t2.Value);
    }

    public static Example2 operator +(Example2 t1, int t2)
    {
        return new Example2(t1.Value + t2);
    }

    public static Example2 operator +(int t1, Example2 t2)
    {
        return new Example2(t1 + t2.Value);
    }
}

and then

Example2 e1 = new Example2(1);
Example2 e2 = new Example2(2);
Example2 sum1 = e1 + e2;
Example2 sum2 = e1 + 4;
Example2 sum3 = 4 + e1;
sum3 += sum1;
sum3 += 1;
int v1 = e1.Value;

(note that the operator+ isn't commutative, so I have to define both the Example2 + int and the int + Example2)

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Wow what a response, thanks very much I had wondered if Nullable<> was using some special "cheats" ;) Your explanation taught me a fair few new things, thank you! – beau c Mar 08 '17 at 12:42
0

Take a look here. You will notice Nullable<T> overloads Implicit conversion operator. That's why T can be implicitly converted to Nullable<T>. If you need other operators you will have to overload them in your class.

Ciprian Lipan
  • 340
  • 2
  • 9
  • 1
    It is the opposite... `T` can be implicitly converted to `T?`. `T?` must be explicitly converted to `T` (because it can throw if `T? == null`) – xanatos Mar 08 '17 at 10:58