Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global type aliases in C#

let me start right away with the code:

class Item {
    public int highestBuyOffer;
    public int lowestSellOffer;
    [...]
}

I would like to prevent people using this class from accidently assigning a buy offer value to a sell offer value and the other way round (like someBuyOffer = someSellOffer). That's why I want to create my own types:

class Item {
    public BuyOffer highestBuyOffer;
    public SellOffer lowestSellOffer;
    [...]
}

Creating a struct for it seems overkill, as these both of values should behave exactly like an int.

The using directive is not what I want because:

  1. It is only valid for one file
  2. It does not count as a type, it's just a synonym
like image 573
MBargus Avatar asked Dec 30 '13 06:12

MBargus


People also ask

What is type alias in C?

typedef is a reserved keyword in the programming languages C and C++. It is used to create an additional name (alias) for another data type, but does not create a new type, except in the obscure case of a qualified typedef of an array type where the typedef qualifiers are transferred to the array element type.

How do Typedefs work in C++?

The typedef keyword allows the programmer to create new names for types such as int or, more commonly in C++, templated types--it literally stands for "type definition". Typedefs can be used both to provide more clarity to your code and to make it easier to make changes to the underlying data types that you use.

What is difference between typedef and #define?

typedef is limited to giving symbolic names to types only, whereas #define can be used to define an alias for values as well, e.g., you can define 1 as ONE, 3.14 as PI, etc. typedef interpretation is performed by the compiler where #define statements are performed by preprocessor.

Is typedef an alias?

The typedef-names are aliases for existing types, and are not declarations of new types. Typedef cannot be used to change the meaning of an existing type name (including a typedef-name).


1 Answers

I made this class to cover identical needs:

public class NamedInt : IComparable<int>, IEquatable<int>
{
    internal int Value { get; }

    protected NamedInt() { }
    protected NamedInt(int val) { Value = val; }
    protected NamedInt(string val) { Value = Convert.ToInt32(val); }

    public static implicit operator int (NamedInt val) { return val.Value; }

    public static bool operator ==(NamedInt a, int b) { return a?.Value == b; }
    public static bool operator ==(NamedInt a, NamedInt b) { return a?.Value == b?.Value; }
    public static bool operator !=(NamedInt a, int b) { return !(a==b); }
    public static bool operator !=(NamedInt a, NamedInt b) { return !(a==b); }

    public bool Equals(int other) { return Equals(new NamedInt(other)); }
    public override bool Equals(object other) {
        if ((other.GetType() != GetType() && other.GetType() != typeof(string))) return false;
        return Equals(new NamedInt(other.ToString()));
    }
    private bool Equals(NamedInt other) {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Equals(Value, other.Value);
    }

    public int CompareTo(int other) { return Value - other; }
    public int CompareTo(NamedInt other) { return Value - other.Value; }

    public override int GetHashCode() { return Value.GetHashCode(); }

    public override string ToString() { return Value.ToString(); }
}

And to consume it in your case:

public class BuyOffer: NamedInt {
    public BuyOffer(int value) : base(value) { }
    public static implicit operator BuyOffer(int value) { return new BuyOffer(value); }
}

public class SellOffer: NamedInt {
    public SellOffer(int value) : base(value) { }
    public static implicit operator SellOffer(int value) { return new SellOffer(value); }
}

If you need to be able to serialize it (Newtonsoft.Json), let me know and I'll add the code.

like image 64
BernardV Avatar answered Sep 19 '22 15:09

BernardV