Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to wrap integer and call it like integer?

Tags:

c#

c#-4.0

I want to make the int in IDictionary<int, Driver> a little less obscure about its meaning, so I thought maybe wrapping it would be a good idea. The outcome would be something like IDictionary<finishPosition, Driver>.

Preferably, finishPosition should be assignable like this finishPosition = 1.

I do not know if this is possible and how.

like image 264
Garth Marenghi Avatar asked Mar 27 '11 19:03

Garth Marenghi


4 Answers

Absolutely, just use this using directive:

using FinishPosition = System.Int32;

at the top of your source file, and write the code just as you have in your example.

If you use the using directive like this, FinishPosition is an int and other files will see it as an int - there is no new type FinishPosition defined (thanks for configurator in the comments).

like image 45
Martin Doms Avatar answered Nov 14 '22 22:11

Martin Doms


You could use a struct with an implicit conversion.

public struct FinishPosition {
    public readonly int Position;

    public FinishPosition(int position) {
        this.Position = position;
    }

    public static implicit operator FinishPosition(int position) {
        return new FinishPosition(position);
    }
}


// ...

Dictionary<FinishPosition, Driver> dict = new Dictionary<FinishPosition, Driver>();
Driver bob = new Driver();

// The following two lines are effectively equivalent
dict[new FinishPosition(7)] = bob;
dict[7] = bob;

// So are these two
bob = dict[7];
bob = dict[new FinishPosition(7)]
like image 130
configurator Avatar answered Nov 14 '22 22:11

configurator


You could use an enum:

enum Position { Finish, Some, Other }

IDictionary<Position, Driver> lookup = ...;

Driver d = lookup[Position.Finish];
like image 40
Henk Holterman Avatar answered Nov 14 '22 23:11

Henk Holterman


In my opinion, it is good to use AbstractDataType pattern anywhere where a general value is used with specific intents (this case has been made by many others with examples like Percentage, ReadonlyString, ConnectionString, etc.)

Note, I personally think that having implicit conversions to and from them sort of hollows the whole thing out (by having an implicit conversion, there is no more compiler guarantee that generic values are being used with specific intent at the right place).

Here is a sample that should inspire you to have it your way: you can still choose the level of convenience/verbosity you prefer. It show two approaches:

  • _byInt indexes a dictionary by PseudoInt
  • _byEnum indexes a dictionary by an Enum : int type

Notes

  • if you #define IMPLICIT_CONVERSIONS you will get implicit conversions to the base index type (so to int or to the enum)
  • this extrapolates to all value types, including user defined ones (try it with your XYZCoord struct :))
  • have a look overhere if you really wanted conversions to and from Enum types

Without further ado:

#define IMPLICIT_CONVERSIONS
using System.Collections.Generic;

namespace NS
{
    public enum PositionEnum : int { Begin = 0, Normal = 1, End = 99 }

    public struct Pseudo<T> where T : struct
    {
        public T Value;
        public Pseudo(T value) { Value = value; }
#if IMPLICIT_CONVERSIONS
        public static implicit operator T(Pseudo<T> pi)  { return pi.Value; }
        public static implicit operator Pseudo<T>(T ni)  { return new Pseudo<T>(ni); }
#endif
    }

    static class Program
    {
        private static Pseudo<T> AsPseudo<T>(this T value) where T : struct
        {
            return new Pseudo<T>(value);
        }

        private static readonly IDictionary<Pseudo<int>, string> _byInt = 
            new Dictionary<Pseudo<int>, string>()
                {   { 0,  "aap" },
                    { 1,  "noot" },
                    { 99, "mies" },
                };

        private static readonly IDictionary<Pseudo<PositionEnum>, string> _byEnum = 
            new Dictionary<Pseudo<PositionEnum>, string>()
                {   { PositionEnum.Begin,  "aap" },
                    { PositionEnum.Normal, "noot" },
                    { PositionEnum.End,    "mies" },
                };

        public static void Main(string[] args)
        {
            string s;
            s = _byInt[0];
            s = _byEnum[PositionEnum.Normal];
        }
    }
}
like image 45
sehe Avatar answered Nov 14 '22 22:11

sehe