Is it possible to wrap integer and call it like integer?
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.
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)]
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).
You could use an enum:
enum Position { Finish, Some, Other }
IDictionary<Position, Driver> lookup = ...;
Driver d = lookup[Position.Finish];
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];
}
}
}
I just adapted the RichEnum generic baseclass in the question I linked before [1]
I'd say I prefer this method because it really seems the most flexible in the long run. The only downside I can think of, really, is that the RichEnum type cannot be a value type anymore.
Head over to see what I mean (includes a fully running sample again):
[1] Can we define implicit conversions of enums in c#?
精彩评论