What's the neatest way to add memoization to a package library - c#

Suppose (entirely hypothetically ;) ) that I have nuget package, which essentially exposes a set of static extension methods:
public static class MyNugetLibrary
{
public static int DoSomethingExpensiveAndUseful(this string input)
{
return input.Length;
}
public static int DoSomethingElseExpensiveAndUseful(this string input)
{
return (int)input.ToCharArray().First();
}
}
And, for sane reasons, I conclude that what this package really needs is caching. The output is constant given the input, and the input is something primitive.
In my case there's no conceivable way for the output to change, so I never have to worry about cache invalidation etc.
If there were just 1 or 2 methods I could just add a private static Dictionary to the extension class, and in the method ask the dictionary for the answer.
But I'd quite like to not duplicate so much code, and there's a really nice memoize function:
public static Func<T, TResult> Memoize<T, TResult>(this Func<T, TResult> f)
{
var cache = new ConcurrentDictionary<T, TResult>();
return a => cache.GetOrAdd(a, f);
}
(Stolen from here: https://www.aleksandar.io/post/memoization/)
But I can't quite figure out how to use that method to make these functions memoized, without changing the external interface of my package.
How can I do this?
Massive bonus points available if we can further do this in such a way that the caching can be disabled by the end user (MyNugetLibrary.DisableCaching()) in case they are worried about, e.g. the memory footprint.

You can use Fody/MethodCache
Run
Install-Package Fody
Install-Package MethodCache.Fody
Then you can change your methods to:
public interface ICache
{
bool Contains(string key);
T Retrieve<T>(string key);
void Store(string key, object data);
void Remove(string key);
}
public static class MyNugetLibrary
{
public static ICache Cache { get; set; } = DefaultCache;
public readonly static ICache DefaultCache = new MemoryCache();
public readonly static ICache NoCache = new UnCache();
[Cache]
public static int DoSomethingExpensiveAndUseful(this string input)
{
return input.Length;
}
[Cache]
public static int DoSomethingElseExpensiveAndUseful(this string input)
{
return (int)input.ToCharArray().First();
}
}

Related

How to deal with optional arguments when wanting to enable nullable reference types?

I see the great advantage of turning on (non-)nullable reference types, but I have quite a few methods with optional parameters and I am wondering what the right way to correct the warnings yielded by the compiler is.
Making the parameter nullable by annotating the type with ? takes all of the goodness away. Another idea is to turn all methods with optional parameters into separate methods, which is quite a lot of work and yields high complexity (exponential explosion of parameter combinations).
I was thinking about something like this, but I really question if that it a good approach (performance-wise etc.) beyond the first glance:
[Fact]
public void Test()
{
Assert.Equal("nothing", Helper().ValueOrFallbackTo("nothing"));
Assert.Equal("foo", Helper("foo").ValueOrFallbackTo("whatever"));
}
public static Optional<string> Helper(Optional<string> x = default)
{
return x;
}
public readonly ref struct Optional<T>
{
private readonly bool initialized;
private readonly T value;
public Optional(T value)
{
initialized = true;
this.value = value;
}
public T ValueOrFallbackTo(T fallbackValue)
{
return initialized ? value : fallbackValue;
}
public static implicit operator Optional<T>(T value)
{
return new Optional<T>(value);
}
}
This look's like F#'s Option. This can be emulated in C# 8 up to a point with pattern matching expressions. This struct :
readonly struct Option<T>
{
public readonly T Value {get;}
public readonly bool IsSome {get;}
public readonly bool IsNone =>!IsSome;
public Option(T value)=>(Value,IsSome)=(value,true);
public void Deconstruct(out T value)=>(value)=(Value);
}
//Convenience methods, similar to F#'s Option module
static class Option
{
public static Option<T> Some<T>(T value)=>new Option<T>(value);
public static Option<T> None<T>()=>default;
...
}
Should allow code like this :
static string Test(Option<MyClass> opt = default)
{
return opt switch
{
Option<MyClass> { IsNone: true } => "None",
Option<MyClass> (var v) => $"Some {v.SomeText}",
};
}
The first option uses property pattern matching to check for None, while the second one uses positional pattern matching to actually extract the value through the deconstructor.
The nice thing is that the compiler recognizes this as an exhaustive match so we don't need to add a default clause.
Unfortunately, a Roslyn bug prevents this. The linked issue actually tries to create an Option class based on an abstract base class. This was fixed in VS 2019 16.4 Preview 1.
The fixed compiler allows us to omit the parameter or pass a None :
class MyClass
{
public string SomeText { get; set; } = "";
}
...
Console.WriteLine( Test() );
Console.WriteLine( Test(Option.None<MyClass>()) );
var c = new MyClass { SomeText = "Cheese" };
Console.WriteLine( Test(Option.Some(c)) );
This produces :
None
None
Some Cheese
VS 2019 16.4 should come out at the same time as .NET Core 3.1 in a few weeks.
Until then, an uglier solution could be to return IsSome in the deconstructor and use positional pattern matching in both cases:
public readonly struct Option<T>
{
public readonly T Value {get;}
public readonly bool IsSome {get;}
public readonly bool IsNone =>!IsSome;
public Option(T value)=>(Value,IsSome)=(value,true);
public void Deconstruct(out T value,out bool isSome)=>(value,isSome)=(Value,IsSome);
public void Deconstruct(out T value)=>(value)=(Value);
}
And
return opt switch { Option<MyClass> (_ ,false) =>"None",
Option<MyClass> (var v,true) => $"Some {v.SomeText}" , };
Borrowing from F# Options
No matter which technique we use, we can add extension methods to the Option static class that mimic F#'s Option module, eg Bind, perhaps the most useful method, applies a function to an Option if it has a value and returns an Option, or returns None if there's no value :
public static Option<U> Bind<T,U>(this Option<T> inp,Func<T,Option<U>> func)
{
return inp switch { Option<T> (_ ,false) =>Option.None<U>(),
Option<T> (var v,true) => func(v) ,
};
}
For example this applies the Format method to an Option to create a Optino :
Option<string> Format(MyClass c)
{
return Option.Some($"Some {c.SomeText}");
}
var c=new MyClass { SomeText = "Cheese"};
var opt=Option.Some(c);
var message=opt.Bind(Format);
This makes it easy to create other helper functions, or chain functions that produce options

What is the "type" of a generic IList<T>?

Imagine an extension like this..
public static Blah<T>(this IList<T> ra)
{
..
}
Imagine you want to make a note of the most recently-called one.
private static IList recent;
public static Blah<T>(this IList<T> ra)
{
recent = ra;
..
}
You actually can not do that:
error CS0266: Cannot implicitly convert type System.Collections.Generic.IList<T> to System.Collections.IList.
1- You can simply make recent an object and that seems to work fine, but it seems like a poor solution.
2- It seems if you do have recent as an IList, you can actually cast the "ra" to that...
recent = (System.Collections.IList)ra;
and it seems to work. Seems strange though?? So,
3- Actually, what type should recent be so that you don't have to cast to it?? How can you make recent the same type as ra? You can't say this ....
private static System.Collections.Generic.IList recent;
it's not meaningful. So what the heck is the type of "ra"? What should recent "be" so that you can simply say recent=ra ?
(I mention this is for Unity, since you constantly use generic extensions in Unity.)
4- Consider a a further difficulty the case if you want to have a Dictionary of them all.
private static Dictionary<object,int> recents = new Dictionary<object,int>();
I can really only see how to do it as an object.
USE CASE EXAMPLE.
Here's an extension you use constantly, everywhere, in game engineering,
public static T AnyOne<T>(this IList<T> ra)
{
int k = ra.Count;
if (k<=0) {Debug.Log("Warn!"+k);}
int r = UnityEngine.Random.Range(0,k);
return ra[r];
}
no problem so far. So,
explosions.AnyOne();
yetAnotherEnemyToDefeat = dinosaurStyles.AnyOne();
and so on. However. Of course, actual random selections feel bad; in practice what you want is a fairly non-repeating order, more like a shuffle. Usually the best thing to do with any list or array is shuffle them, and serve them in that order; perhaps shuffle again each time through. Simple example, you have 20 random sound effects roars , being for when the dino roars. Each time you need one, if you do this
roars.AnyOne();
its OK, but not great. It will sound sort of suck. (Most players will report it as "not being random" or "repeating a lot".) This
roars.NextOne();
is much better. So, NextOne() should, on its own, (a) if we're at the start shuffle the list, (b) serve it in that order, (c) perhaps shuffle it again each time you use up the list. {There are further subtleties, eg, try not to repeat any near the end/start of the reshuffle, but irrelevant here.}
Note that subclassing List (and/or array) would suck for many obvious reasons, it's a job for a simple self-contained extension.
So then, here's a beautiful way to implement NextOne() using a simple stateful extension.
private static Dictionary<object,int> nextOne = new Dictionary<object,int>();
public static T NextOne<T>(this IList<T> ra)
{
if ( ! nextOne.ContainsKey(ra) )
// i.e., we've never heard about this "ra" before
nextOne.Add(ra,0);
int index = nextOne[ra];
// time to shuffle?
if (index==0)
{
Debug.Log("shuffling!"); // be careful to mutate, don't change the ra!
IList<T> temp = ra.OrderBy(r => UnityEngine.Random.value).ToList();
ra.Clear(); foreach(T t in temp) ra.Add(t);
}
T result = ra[index];
++index;
index=index%ra.Count;
nextOne[ra] = index;
return result;
}
This is surely the perfect example of a "stateful extension".
Notice indeed, I just used "object".
I guess in a way, the fundamental question in this QA is, is it best to use the Dictionary of "object" there, or, would something else more typey be better? Really that's the question at hand. Cheers!
If you want a single globally most recent IList<T> where T potentially varies each time, then your only options are to use object or dynamic. Both require casting; the latter just casts automatically.
I think your confusion stems from thinking that IList<T> inherits IList - it doesn't:
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
So arguably you could do this, although I don't see any advantage really:
private static IEnumerable recent;
public static void Blah<T>(this IList<T> ra)
{
recent = ra;
...
}
The simplest, and most type-safe, solution is to store a separate value for each T:
private static class RecentHolder<T> {
public static IList<T> Value { get; set; }
}
public static Blah<T>(this IList<T> ra) {
RecentHolder<T>.Value = ra;
}
What is the “type” of a generic IList< T >?
The base type..
Console.WriteLine( new List<int>().GetType().BaseType);
System.Object
The Generic Type definition ...
Console.WriteLine( new List<int>().GetType().GetGenericTypeDefinition());
System.Collections.Generic.List`1[T]
And to expand on SLAKS Answer
Not really. In the absence of a separate common non-generic base class
You can also use interfaces. So you could do...
public interface IName
{
string Name { get; set; }
}
public class Person : IName
{
public string Name { get; set; }
}
public class Dog : IName
{
public string Name { get; set; }
}
Then you could
private static List<IName> recent;
public static Blah<T>(this List<IName> ra)
{
recent = ra;
..
}
and it won't matter if you put Dog or Person in the list.
OR
I can't believe I didn't think about this last night; LINQ to the rescue using object.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
private static class WonkyCache
{
private static List<object> cache = new List<object>();
public static void Add(object myItem)
{
cache.Add(myItem);
}
public static IEnumerable<T> Get<T>()
{
var result = cache.OfType<T>().ToList();
return result;
}
}
public static void Main()
{
WonkyCache.Add(1);
WonkyCache.Add(2);
WonkyCache.Add(3);
WonkyCache.Add(Guid.NewGuid());
WonkyCache.Add("George");
WonkyCache.Add("Abraham");
var numbers = WonkyCache.Get<int>();
Console.WriteLine(numbers.GetType());
foreach(var number in numbers)
{
Console.WriteLine(number);
}
var strings = WonkyCache.Get<string>();
Console.WriteLine(strings.GetType());
foreach(var s in strings)
{
Console.WriteLine(s);
}
}
}
Results:
System.Collections.Generic.List`1[System.Int32]
1
2
3
System.Collections.Generic.List`1[System.String]
George
Abraham
Try:
public static class StatefulRandomizer<T>
// Use IEquatable<T> for Intersect()
where T : IEquatable<T>
{
// this could be enhanced to be a percentage
// of elements instead of hardcoded
private static Stack<T> _memory = new Stack<T>();
private static IEnumerable<T> _cache;
public static void UpdateWith(IEnumerable<T> newCache)
{
_cache = newCache.ToList();
// Setup the stack again, keep only ones that match
var matching = _memory.Intersect(newCache);
_memory = new Stack<T>(matching);
}
public static T GetNextNonRepeatingRandom()
{
var nonrepeaters = _cache
.Except(_memory);
// Not familar with unity.. but this should make
// sense what I am doing
var next = nonrepeaters.ElementAt(UnityEngine.Random(0, nonrepeaters.Count()-1));
// this fast, Stack will know it's count so no GetEnumerator()
// and _cache List is the same (Count() will call List.Count)
if (_memory.Count > _cache.Count() / 2)
{
_memory.Pop();
}
_memory.Push(next);
return next;
}
}

What is the best approach for caching database queries

I'm writing a management intelligence application which requires quite a lot of complex database querying with some queries being quite expensive. To aid performance I'm using Memcached quite heavily to store as much as I can in memory.
This has led to quite a lot of duplication in my code which I'm eager to get rid of and build a cleaner data access solution. Quite a lot of my data access functions have ended up looking like this..
public int NumberOfTimeouts(DateTime date, int? applicationId)
{
var functionCacheKey = "NumberOfTimeouts";
var cacheKey = string.Format("{0}-{1}-{2}-{3}", RepositoryCacheKey, functionCacheKey, date, applicationId);
var cachedNumberTimeouts = _cache.Retrieve(cacheKey);
if (cachedNumberTimeouts != null)
{
return (int)cachedNumberTimeouts;
}
//query logic here, calculates numberOfTimeouts
UpdateCache(date, cacheKey, numberOfTimeouts);
return numberOfTimeouts;
}
I'm just not too sure what the standard approach is to this, could it involve using a custom attribute class or something similar?
This is a cross-cutting concern. The Decorator pattern may be applicable here. I may be inexperienced in this pattern, however I will give it a shot
// model
public class CustomObject
{
public int Id { get; set; }
}
// interface
public interface IRepository<T>
{
IEnumerable<T> Find(Expression<Func<T, bool>> expression);
}
public interface ICacheableRepository<T>
{
IEnumerable<T> Find(Expression<Func<T, bool>> expression, Func<int> cacheKey);
}
public interface IRepositoryCacheManager<T>
{
IEnumerable<T> Get(int key);
bool Any(int key);
void Add(int key, IEnumerable<T> result);
}
// cache manager
public class RepositoryCacheManager<T> : IRepositoryCacheManager<T>
{
private Dictionary<int, IEnumerable<T>> cache = new Dictionary<int,IEnumerable<T>>();
#region IRepositoryCache<T> Members
public IEnumerable<T> Get(int key)
{
return cache[key];
}
public bool Any(int key)
{
IEnumerable<T> result = null;
return cache.TryGetValue(key, out result);
}
public void Add(int key, IEnumerable<T> result)
{
cache.Add(key, result);
}
#endregion
}
// cache repository decorator
public class CachedRepositoryDecorator<T> : IRepository<T>, ICacheableRepository<T>
{
public CachedRepositoryDecorator(IRepositoryCacheManager<T> cache
, IRepository<T> member)
{
this.member = member;
this.cache = cache;
}
private IRepository<T> member;
private IRepositoryCacheManager<T> cache;
#region IRepository<T> Members
// this is not caching
public IEnumerable<T> Find(Expression<Func<T, bool>> expression)
{
return member.Find(expression);
}
#endregion
#region ICacheableRepository<T> Members
public IEnumerable<T> Find(Expression<Func<T, bool>> expression, Func<int> cacheKey)
{
if (cache.Any(cacheKey()))
{
return cache.Get(cacheKey());
}
else
{
IEnumerable<T> result = member.Find(expression);
cache.Add(cacheKey(), result);
return result;
}
}
#endregion
}
// object repository
public class CustomObjectRepository : IRepository<CustomObject>
{
#region IRepository<CustomObject> Members
public IEnumerable<CustomObject> Find(Expression<Func<CustomObject, bool>> expression)
{
List<CustomObject> cust = new List<CustomObject>();
// retrieve data here
return cust;
}
#endregion
}
// example
public class Consumer
{
// this cache manager should be persistent, maybe can be used in static, etc
IRepositoryCacheManager<CustomObject> cache = new RepositoryCacheManager<CustomObject>();
public Consumer()
{
int id = 25;
ICacheableRepository<CustomObject> customObjectRepository =
new CachedRepositoryDecorator<CustomObject>(
cache
, new CustomObjectRepository()
);
customObjectRepository.Find(k => k.Id == id, () => { return id; });
}
}
Please note:
I haven't tested this code, don't know whether it is fully functional or not. I just describe the illustration
Yes, this has code smell by having the ICacheableRepository overloading for Find, however I am incapable in using Expression as Key in Dictionary
The pros:
This CachedRepositoryDecorator can be used to ANY generic repository (reusable)
No caching logic inside the select process, emphasize SRP
The cons:
Hard to implement without ORM, maybe you will need some tweaks with reflection to make it works without ORM
Hard to understand at beginning
Hard to wire without DI Container
Credit to this article :)
I think the Unit of Work pattern is what you need.
More info:
http://martinfowler.com/eaaCatalog/unitOfWork.html
http://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern
http://msdn.microsoft.com/en-us/magazine/dd882510.aspx
Or a framework that contains the UoW pattern: https://github.com/riteshrao/ncommon

Fixed container, enumerable, intellisense indexable (or member)

I'm trying to make an object to hold some strings. The object can be anything, including collections, arrays ... The strings need to be enumerable (IEnumerable or similar). Each string indexer needs to be known by intellisense and Reflection is a last option. One single object, no separate object for indexers.
Example usage:
public static class features
{
public const string favorite = "blue background";
public const string nice = "animation";
}
public static class Program
{
public static void Main()
{
foreach (string feature in features)
{
Console.WriteLine(feature);
}
//... select a feature
Console.WriteLine(features.favorite);
}
}
EDIT:
I will use the first solution proposed by Jim Mischel, modified to use reflection, as that gets the advantages I'm interested in at the current time.
encapsulates everything in one entity
names are directly associated with values
enumerator is dynamic
public IEnumerator<string> GetEnumerator()
{
FieldInfo[] strings = this.GetType().GetFields();
foreach (FieldInfo currentField in strings)
{
yield return currentField.GetValue(null).ToString();
}
yield break;
}
I thank everyone for your effort.
Offhand, I can think of two ways to do it. However, since it must be IEnumerable<string> it can't be a static class because static classes can't implement interfaces. Nor can static methods implement interface methods.
The first way uses constants and an enumerator that just returns them in order:
public class Features: IEnumerable<string>
{
public const string Favorite = "blue background";
public const string Nice = "animation";
public IEnumerator<string> GetEnumerator()
{
yield return Favorite;
yield return Nice;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
The second way stores the values in an array and uses an enum for the indexes. The enumerator just returns the enumerator for the array. Again, this is not static because of the enumerator, and also because indexers can't be static.
public enum FeaturesIndex
{
Favorite = 0,
Nice = 1
}
public class Features2 : IEnumerable<string>
{
private static readonly string[] _features = new string[]
{
"blue background",
"animation"
};
public string this [FeaturesIndex ix]
{
get { return _features[(int) ix]; }
}
public IEnumerator<string> GetEnumerator()
{
return ((IEnumerable<string>) _features).GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
A third possibility, as pointed out by others, is using a dictionary and either an enumeration or defined constants as keys. It's an interesting approach, the only potential drawback being that you can't guarantee the order in which keys will be returned when you enumerate the collection. If that's a problem, you could have your enumerator sort the sequence before returning.
Any way you look at it, there are tradeoffs. Both of my solutions require manual synchronization of keys and values. In the first, you have to make sure that the enumerator retures all of the values. In the second, you have to ensure that your enum matches the array.
Pick your poison.
It also depends on how you're going to use the thing. My first solution has the benefit of simplicity and would probably be quite acceptable if it's a write-once, use-forever kind of thing. The second option has the benefit of using an indexer, which is more commonly associated with collections.
There are many better ways to do this. To follow a similar pattern to what you're looking for, here's one way of doing it:
public static class features
{
public enum TYPES { favorite, nice }
public static Dictionary<TYPES,string> values = new Dictionary<TYPES,string>() {
{ TYPES.favorite, "blue background" },
{ TYPES.nice, "animation" } };
}
public static class Program
{
public static void Main()
{
foreach (string feature in features.values.keys)
{
Console.WriteLine(features.values[feature]);
}
//... select a feature
Console.WriteLine(features.values[TYPES.favorite]);
}
}
So really what you are asking for is an object with Properties you can change and is also enumerable, but makes it so you don't need to call reflection to enumerate unless absolutely necessary.
If what I assume you are actually looking is the following
public class Features: IEnumerable<string>
{
private readonly Dictionary<string,string> _internalCollection;
public Features()
{
_internalCollection = new Dictionary<string,string>();
}
private string GetByKey(string id)
{
if(!_internalCollection.ContainsKey(id))
return null;
return _internalCollection[id];
}
private void SetByKey(string id, string value)
{
_internalCollection[id]=value;
}
const string _favoriteId = "favorite";
public string Favorite
{
get { return GetByKey(_favoriteId); }
set { return SetByKey(_favoriteId,value);}
}
const string _niceId = "nice";
public string Nice
{
get { return GetByKey(_niceId);}
set { return SetByKey(_niceId, value);}
}
public string this[string index]
{
get { return GetByKey(index.ToLower()); }
set { return SetByKey(index.ToLower(), value);}
}
public IEnumerator<string> GetEnumerator()
{
foreach(var key in _internalCollection.Keys)
yield return _internalCollection[key];
yield break;
}
}

java enums vs C# enums - missing features

in java I could easily describe an enum with aditional data.
I could describe it something like this
public enum OperatorType
{
GreaterOrEqual (">=", "GreaterOrEqual"),
Greater (">" ,"Greater"),
Less ("<", "Less"),
LessOrEqual ("<=", "LessOrEqual"),
Equal ("==", "Equal"),
Between ("Between", "Between"),
Around ("Around","Around");
private final String symbol;
private final String name;
private OperatorType(final String symbol, final String name) {
this.symbol = symbol;
this.name = name;
}
}
And then add a static method that iterates over values(), adds all data to a hashmap and allow to retrieve from the map full enum data by one of its attriburtes as a key.
In brief, enum is a very developed type in java.
Now,
moving to c#, what are my options?
I want to hold an enum with its attributes, load it to a map, and retreive by key when I need. Do I have anything to assist (like, a singletone for each enum - which is not a good idea).
Thanks.
I would just create a class with public static readonly instances of each type and ditch enums altogether. You can use them as dictionary keys or do whatever you like. If you still intend to map them to an underlying data type (int) then you can create implicit operators for that too.
public class OperatorType
{
private static readonly Dictionary<int, OperatorType> OperatorMapping = new Dictionary<int, OperatorType>();
public static readonly OperatorType GreaterOrEqual = new OperatorType(0, ">=", "GreaterOrEqual");
public static readonly OperatorType Greater = new OperatorType(1, ">", "Greater");
public readonly String symbol;
public readonly String name;
private readonly int underlyingValue;
private OperatorType(int underlyingValue, string symbol, string name) {
this.underlyingValue = underlyingValue;
OperatorMapping[underlyingValue] = this;
this.symbol = symbol;
this.name = name;
}
public static implicit operator int(OperatorType operatorType)
{
return operatorType.underlyingValue;
}
public static implicit operator OperatorType(int value)
{
return OperatorMapping[value];
}
}
Sample usage:
Dictionary<OperatorType, string> operators = new Dictionary<OperatorType, string>();
operators.Add(OperatorType.GreaterOrEqual, "Greater or equal");
Console.WriteLine(operators[OperatorType.GreaterOrEqual]); //"Greater or equal"
OperatorType operatorType = 1;
Console.WriteLine(operatorType.name); //"Greater"
If you don't care about an underlying value, don't include it. Also consider whether or not the Dictionary mapping should be threadsafe for your usage. You can also expose a static IEnumerable<OperatorType> (or other collection) to get all operators defined if you want.
EDIT: On second thought, explicit operators are possibly preferable instead of implicit, both to conform with typical .NET best practices and to better match typical enum conversions.
The most convinient workaround might be to create an extension method to your enum type, and return the associated symbols.
Something like this:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
tester t = tester.x;
t.testenums();
Console.ReadKey();
}
}
public static class ext
{
public static void testenums(this tester x)
{
Console.WriteLine(x.ToString());
}
}
public enum tester
{
x,
y
}
}
Of course you can write a more complex extension method, with return value, etc, this is just an example how to do it.
You can create an attribute:
public class EnumKeyAttribute : Attribute
{
public string Key { get; set; }
public string Description { get; set; }
public EnumKeyAttribute(string key, string description)
{
this.Key = key;
this.Description = description;
}
}
Then apply it to your enum
public enum OperatorType
{
[EnumKey(">=", "GreaterOrEqual")]
GreaterOrEqual,
[EnumKey(">", "Greater")]
Greater,
[EnumKey("<", "Less")]
Less,
[EnumKey("<=", "LessOrEqual")]
LessOrEqual,
[EnumKey("==", "Equal")]
Equal,
[EnumKey("Between", "Between")]
Between,
[EnumKey("Around", "Around")]
Around
}
To get the attribute data you can use reflection. Below is an example of getting the attribute for "Less"
MemberInfo memberInfo = typeof(OperatorType).GetMember(OperatorType.Less.ToString()).FirstOrDefault();
if(memberInfo != null)
{
EnumKeyAttribute attribute = (EnumKeyAttribute)memberInfo.GetCustomAttributes(typeof(EnumKeyAttribute), false).FirstOrDefault();
Console.WriteLine(attribute.Key);
Console.WriteLine(attribute.Description);
}
But because these enums are not created at runtime you can increase your efficiency by creating a static method that looks up the value in a dictionary. Do this as an extension method for ease of use
public static class KeyFinder
{
private static Dictionary<OperatorType, EnumKeyAttribute> lookupTable =
new Dictionary<OperatorType, EnumKeyAttribute>();
public static EnumKeyAttribute GetKey(this OperatorType type)
{
if (lookupTable.ContainsKey(type))
{
return lookupTable[type];
}
MemberInfo memberInfo = typeof(OperatorType).GetMember(type.ToString()).FirstOrDefault();
if (memberInfo != null)
{
EnumKeyAttribute attribute = (EnumKeyAttribute)memberInfo.GetCustomAttributes(typeof(EnumKeyAttribute), false).FirstOrDefault();
if (attribute != null)
{
lookupTable.Add(type, attribute);
return attribute;
}
}
// add a null value so next time it doesn't use reflection only to find nothing
lookupTable.Add(type, null);
return null;
}
}
So now to get the values you simply do the following:
OperatorType.Less.GetKey().Key
OperatorType.Less.GetKey().Description
Just be careful of null reference exceptions (since it will return null if it can't find an attribute). If you want to find by key you can simply create other extension methods that use the string value as the key.
C# doesn't really have the same feature. However there are several possibilities to get really close (and potentially more flexible as well).
Sticking to regular enums, you could use attributes to enrich with extra information. Of course, this requires reflection to work with that
public enum OperatorType
{
[DisplayName(">=")]
GreaterOrEqual,
// ...
}
There are several patterns to work with this, e.g. http://www.codeproject.com/Articles/28087/DisplayNameAttribute-for-Enumerations, google for more.
Another approach can be to enhance your enumeration types using regular classes:
public class OperatorType
{
public static OperatorType GreaterOrEqual = new OperatorType(">=", "GreaterOrEqual");
// ...
string symbol;
string name;
private OperatorType(string symbol, string name)
{
this.symbol = symbol;
this.name = name;
}
}
This article describes some other ways to work with enum-like types in C#
If you really need the functionality of Java-style enums in C#, I see three reasonable ways to implement it:
Use a C# enum and a static class of helper methods. You lose type safety, but this is an otherwise very workable solution.
Use a C# enum and a set of extension methods. Probably the most idiomatic C# solution, but you still have to deal with the loss of type safety (your extension methods should be able to cope with out-of-range values, even if only by throwing an exception).
Use the type-safe enum pattern that was common in Java before the language gained the enum keyword in Java 5. If you have non-trivial logic for each enum value, this would be my preference.

Categories

Resources