How to add extension methods to Enums - c#

I have this Enum code:
enum Duration { Day, Week, Month };
Can I add a extension methods for this Enum?

According to this site:
Extension methods provide a way to write methods for existing classes in a way other people on your team might actually discover and use. Given that enums are classes like any other it shouldn’t be too surprising that you can extend them, like:
enum Duration { Day, Week, Month };
static class DurationExtensions
{
public static DateTime From(this Duration duration, DateTime dateTime)
{
switch (duration)
{
case Day: return dateTime.AddDays(1);
case Week: return dateTime.AddDays(7);
case Month: return dateTime.AddMonths(1);
default: throw new ArgumentOutOfRangeException("duration");
}
}
}
I think enums are not the best choice in general but at least this lets you centralize some of the switch/if handling and abstract them away a bit until you can do something better. Remember to check the values are in range too.
You can read more here at Microsft MSDN.

You can also add an extension method to the Enum type rather than an instance of the Enum:
/// <summary> Enum Extension Methods </summary>
/// <typeparam name="T"> type of Enum </typeparam>
public class Enum<T> where T : struct, IConvertible
{
public static int Count
{
get
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
return Enum.GetNames(typeof(T)).Length;
}
}
}
You can invoke the extension method above by doing:
var result = Enum<Duration>.Count;
It's not a true extension method. It only works because Enum<> is a different type than System.Enum.

Of course you can, say for example, you want to use the DescriptionAttribue on your enum values:
using System.ComponentModel;
public enum Duration
{
[Description("Eight hours")]
Day,
[Description("Five days")]
Week,
[Description("Twenty-one days")]
Month
}
Now you want to be able to do something like:
Duration duration = Duration.Week;
var description = duration.GetDescription(); // will return "Five days"
Your extension method GetDescription() can be written as follows:
using System.ComponentModel;
using System.Reflection;
public static string GetDescription(this Enum value)
{
FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
if (fieldInfo == null) return null;
var attribute = (DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));
return attribute.Description;
}

All answers are great, but they are talking about adding extension method to a specific type of enum.
What if you want to add a method to all enums like returning an int of current value instead of explicit casting?
public static class EnumExtensions
{
public static int ToInt<T>(this T soure) where T : IConvertible//enum
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
return (int) (IConvertible) soure;
}
//ShawnFeatherly funtion (above answer) but as extention method
public static int Count<T>(this T soure) where T : IConvertible//enum
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be an enumerated type");
return Enum.GetNames(typeof(T)).Length;
}
}
The trick behind IConvertible is its Inheritance Hierarchy see MDSN
Thanks to ShawnFeatherly for his answer

A Simple workaround.
public static class EnumExtensions
{
public static int ToInt(this Enum payLoad) {
return ( int ) ( IConvertible ) payLoad;
}
}
int num = YourEnum.AItem.ToInt();
Console.WriteLine("num : ", num);

You can create an extension for anything, even object(although that's not considered best-practice). Understand an extension method just as a public static method. You can use whatever parameter-type you like on methods.
public static class DurationExtensions
{
public static int CalculateDistanceBetween(this Duration first, Duration last)
{
//Do something here
}
}

See MSDN.
public static class Extensions
{
public static string SomeMethod(this Duration enumValue)
{
//Do something here
return enumValue.ToString("D");
}
}

we have just made an enum extension for c# https://github.com/simonmau/enum_ext
It's just a implementation for the typesafeenum, but it works great so we made a package to share - have fun with it
public sealed class Weekday : TypeSafeNameEnum<Weekday, int>
{
public static readonly Weekday Monday = new Weekday(1, "--Monday--");
public static readonly Weekday Tuesday = new Weekday(2, "--Tuesday--");
public static readonly Weekday Wednesday = new Weekday(3, "--Wednesday--");
....
private Weekday(int id, string name) : base(id, name)
{
}
public string AppendName(string input)
{
return $"{Name} {input}";
}
}
I know the example is kind of useless, but you get the idea ;)

Related

Methods in c# enums

In Java we can use methods in enums, for example i can write
public static void main(String []args){
System.out.println(GetNum.TWO.get());
}
enum GetNum{
ONE{
public int get(){
return 1;
}
},
TWO{
public int get(){
return 2;
}
};
public abstract int get();
}
maybe somebody can say me: in c# enums can I do something like this?
Not really, but you can sort of though the use of extension methods.
Given an enumeration such as
enum HurfDurf
{
Hurr,
Durr
}
you can create an extension method such as
static class HurfDurfExtensions
{
public static string Wat(this HurfDurf lol)
{
return lol == HurfDurf.Hurr ? "Wew lad" : "eyy boss";
}
}
and use it like
var whatisthisidonteven = HurfDurf.Hurr.Wat();
No you can't. In the background enum are value-types (e.g. just an int).
E.g. you can do int i = (int)yourEnum;and vice versa.

C# - No implicit reference conversion from 'T' to 'System.IComparable<T>'

I have taken the following class from another SO question:
public class Range<T> where T : IComparable<T>
{
public T Minimum { get; set; }
public T Maximum { get; set; }
public override string ToString() { return String.Format("[{0} - {1}]", Minimum, Maximum); }
public Boolean IsValid() { return Minimum.CompareTo(Maximum) <= 0; }
public Boolean ContainsValue(T value)
{
return (Minimum.CompareTo(value) <= 0) && (value.CompareTo(Maximum) <= 0);
}
}
I would like, however, to create another class that contains many instances of this class, and can execute a foreach loop on them all, returning true if the number passed is contained in any one of the ranges:
public class Ranges<T> where T : Range<T>
{
private List<Range<T>> rangelist;
public void add(Range<T> range)
{
rangelist.Add(range);
}
public Boolean ContainsValue(T value)
{
foreach (Range<T> range in rangelist)
{
if (range.ContainsValue(value)) return true;
}
return false;
}
}
However, i am getting the error The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Range<T>'. There is no implicit reference conversion from 'T' to 'System.IComparable<T>'.
What exactly is going wrong here?
You don't seem to need the constraint where T : Range<T>
Just repeat the comparable constraint:
public class Ranges<T> where T : IComparable<T>
{
}
If you rewrite your second class slightly, you'll see why:
public class Ranges<U> where U : Range<U>
{
private List<Range<U>> rangelist;
public void add(Range<U> range)
{
rangelist.Add(range);
}
...
}
The error is telling you the compiler does not know if U is convertible to IComparable<U>, which is apparent from the declaration of Ranges<U> and Range<T> (Range<T> does not implement any interfaces).
More importantly, you have a recursing generic argument!
If U is Range<U>, then your class looks like Ranges<Range<T>> where T is U, and so on and so forth.
From what I can tell, you're not looking to write:
Ranges<Range<int>> x = ...;
But rather:
Ranges<int> x = ...;
Which would mean:
public class Ranges<T> where T : IComparable<T>
{
private List<Range<T>> rangelist;
...
You don't need new classes for that, use linq.
list1.All(x=>list2.Any(y=>y == x))
UPDATE: You are saying : I would like, however, to create another class that contains many instances of this class, and can execute a foreach loop on them all, returning true if the number passed is contained in any one of the ranges:
So effectively you have list of lists. Or more generally IEnumerable of IEnumerables.
There is enough standard generic data structures to handle this scenario
public static class ListOfListExtention {
public static bool ContainAny( this List<List<int>> lists, int number ) {
return lists.Any(l=>l.Any(x=>x == number))
}
}
Which can be rewritten in more generic way using IComparable interface
public static class ListOfListExtention {
public static bool ContainAny<T>
(this List<List<int>> lists, int value ) where T : IComparable<T> {
return lists.Any(l=>l.Any(x=>x == value))
}
}
So to compare with accepted answer, why wrap List in new class if you can just have one extension method.

Get MethodInfo for any method with any signature (delegate for any signature)

I want to write a method that will analyze custom attributes of any method (with any number of arguments and any return type) knowing only method info.
This function will check if method has specific Attribute. like this: var tmp = methodInfo.GetCustomAttributes(typeof(LineItemAttribute),false); and if it has such attribute It will execute it.And I want to make call of that function really easy to use. So, in example there are three methods and method GetMethodAttributes that I want to call.
class Test
{
public static void Main()
{
}
public void Test1(){}
public void Test2(int a){}
public void Test3(object a, string c, Boolean d);
public void GetMethodAttributes(MethodInfo mi) {}
}
Ideally I want to write something like that
public static void Main()
{
var t = new Test();
GetMethodAttributes(t.Test1);
GetMethodAttributes(t.Test2);
GetMethodAttributes(t.Test3);
}
I don't want to use string representation of the method names as method names may change, like that:
MethodInfo info = type.GetMethod(name);
Do I have any options? Basically I need a way to use delegates for functions with different sinatures
As Chris Sinclair pointed out in the comment above; you can use a delegate without using reflection or expression trees to get the MethodInfo. The downside is that the compiler is not able to infer the generic parameter so you have to specify the delegate type to match the signature of the given method like this:
public class Test
{
public static void Main()
{
var t = new Test();
CheckMethodAttributes<Action>(t.Test1);
CheckMethodAttributes<Action<int>>(t.Test2);
CheckMethodAttributes<Action<object, string, bool>>(t.Test3);
}
public void Test1() { }
public void Test2(int a) { }
public void Test3(object a, string c, bool d) { }
public static void CheckMethodAttributes<T>(T func)
{
MethodInfo method = new MethodOf<T>(func);
// Example attribute check:
var ignoreAttribute = method.GetAttribute<IgnoreAttribute>();
if (ignoreAttribute != null)
{
// Do something here...
}
}
}
This uses two utility classes, the MethodOf<T> for extracting the MethodInfo from the given Delegate and some AttributeUtils to get strongly typed custom attribute retrieval:
public static class AttributeUtils
{
public static bool HasAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.IsDefined(typeof(TAttribute), inherit);
}
public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetAttributes<TAttribute>(inherit).FirstOrDefault();
}
public static IEnumerable<TAttribute> GetAttributes<TAttribute>(this MemberInfo member, bool inherit = true)
where TAttribute : Attribute
{
return member.GetCustomAttributes(typeof(TAttribute), inherit).Cast<TAttribute>();
}
}
public class MethodOf<T>
{
public MethodOf(T func)
{
var del = func as Delegate;
if (del == null) throw new ArgumentException("Cannot convert func to Delegate.", "func");
Method = del.Method;
}
private MethodInfo Method { get; set; }
public static implicit operator MethodOf<T>(T func)
{
return new MethodOf<T>(func);
}
public static implicit operator MethodInfo(MethodOf<T> methodOf)
{
return methodOf.Method;
}
}
You can do something like this using Expression Trees, where you pass the method via a lambda expression. You do still need to pass stub values for the parameters, however. For a good example of this in action, check out the source code for Moq, which uses this pattern extensively for setting up mock behaviors for unit testing. Just note that this is not a trivial thing to set up. If you need something relatively quick and dirty, your best bet is probably string names with a good refactoring tool and/or automated tests to help deal with the renaming issues.

How to implement a "convert using this function" custom attribute in .Net?

I'm building some stuff out using Attributes. One thing I'd really like to implement as an attribute is a convert a string to this property's type using this function. Right now, I have this:
public delegate object ParameterConverter(string val);
[AttributeUsage(AttributeTargets.Property)]
public class ParameterConverterAttribute : ParameterBaseAttribute
{
ParameterConverter Converter;
public ParameterConverterAttribute(ParameterConverter converter)
{
Converter=converter;
}
public object Convert(string val)
{
return Converter(val);
}
}
And I use it like so:
public class Tester
{
[ParameterConverter(new ParameterConverter(TestConverter)] //error here
public int Foo{get;set;}
static object TestConverter(string val)
{
return 10;
}
}
However, .Net or at least C# doesn't appear to support this kind of thing. It appears that delegates inside of attributes doesn't work.
Is there any workarounds to this issue or a good way to deal with this problem?
No Delegates cannot be passed as an argument to an Attribute. The Supported types are :
Object
Type
Enum
Single Dimentional Array
bool, byte, float char, double, int, long, string .... etc.
But as it supports Type as well as strings, you can pass a Type and the name of the method to create a delegate inside the Attribute class.
public delegate object ParameterConverter(string val);
[AttributeUsage(AttributeTargets.Property)]
public class ParameterConverterAttribute : ParameterBaseAttribute
{
public ParameterConverter Converter { get; set; }
public ParameterConverterAttribute(Type delegateType, string method)
{
try{ // Important as GetMethod can throw error exception or return null
this.Converter = (ParameterConverter)Delegate.CreateDelegate(delegateType, delegateType.GetMethod(method));
}
catch { }
}
public object Convert(string val)
{
if(this.Converter != null)
return Converter(val);
}
}
And now you can use it like :
public class Tester
{
[ParameterConverter(typeof(ParameterConverter), "TestConverter"]
public int Foo{get;set;}
static object TestConverter(string val)
{
return 10;
}
}
I hope this would help you.
Lookup for TypeConverter class
or
Type Converter Example
This example shows how to create a type converter named AuthorConverter....The AuthorConverter example converts an Author object to a String and a String representation to an Author object.
UPDATE:
You can skip the limitations of attributes like #abhishek has shown.
Possible another way is to define some "convention over configuration": converter function is a method defined like so
private static Converter(string val) defined inside same class. In your case:
public class Tester
{
public int Foo{get;set;}
private static int FooConverter(string val)
{
return 10;
}
}
You can put some ParameterConverterAttribute on top of the property as a sign that custom converter function exists, but is not mandatory.

Anyone know a good workaround for the lack of an enum generic constraint?

What I want to do is something like this: I have enums with combined flagged values.
public static class EnumExtension
{
public static bool IsSet<T>( this T input, T matchTo )
where T:enum //the constraint I want that doesn't exist in C#3
{
return (input & matchTo) != 0;
}
}
So then I could do:
MyEnum tester = MyEnum.FlagA | MyEnum.FlagB
if( tester.IsSet( MyEnum.FlagA ) )
//act on flag a
Unfortunately, C#'s generic where constraints have no enum restriction, only class and struct. C# doesn't see enums as structs (even though they are value types) so I can't add extension types like this.
Does anyone know a workaround?
EDIT: This is now live in version 0.0.0.2 of UnconstrainedMelody.
(As requested on my blog post about enum constraints. I've included the basic facts below for the sake of a standalone answer.)
The best solution is to wait for me to include it in UnconstrainedMelody1. This is a library which takes C# code with "fake" constraints such as
where T : struct, IEnumConstraint
and turns it into
where T : struct, System.Enum
via a postbuild step.
It shouldn't be too hard to write IsSet... although catering for both Int64-based and UInt64-based flags could be the tricky part. (I smell some helper methods coming on, basically allowing me to treat any flags enum as if it had a base type of UInt64.)
What would you want the behaviour to be if you called
tester.IsSet(MyFlags.A | MyFlags.C)
? Should it check that all the specified flags are set? That would be my expectation.
I'll try to do this on the way home tonight... I'm hoping to have a quick blitz on useful enum methods to get the library up to a usable standard quickly, then relax a bit.
EDIT: I'm not sure about IsSet as a name, by the way. Options:
Includes
Contains
HasFlag (or HasFlags)
IsSet (it's certainly an option)
Thoughts welcome. I'm sure it'll be a while before anything's set in stone anyway...
1 or submit it as a patch, of course...
As of C# 7.3, there is now a built-in way to add enum constraints:
public class UsingEnum<T> where T : System.Enum { }
source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
Darren, that would work if the types were specific enumerations - for general enumerations to work you have to cast them to ints (or more likely uint) to do the boolean math:
public static bool IsSet( this Enum input, Enum matchTo )
{
return ( Convert.ToUInt32( input ) & Convert.ToUInt32( matchTo ) ) != 0;
}
As of C# 7.3, you can use the Enum constraint on generic types:
public static TEnum Parse<TEnum>(string value) where TEnum : Enum
{
return (TEnum) Enum.Parse(typeof(TEnum), value);
}
If you want to use a Nullable enum, you must leave the orginial struct constraint:
public static TEnum? TryParse<TEnum>(string value) where TEnum : struct, Enum
{
if( Enum.TryParse(value, out TEnum res) )
return res;
else
return null;
}
Actually, it is possible, with an ugly trick.
However, it cannot be used for extension methods.
public abstract class Enums<Temp> where Temp : class {
public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
return (TEnum)Enum.Parse(typeof(TEnum), name);
}
}
public abstract class Enums : Enums<Enum> { }
Enums.IsSet<DateTimeKind>("Local")
If you want to, you can give Enums<Temp> a private constructor and a public nested abstract inherited class with Temp as Enum, to prevent inherited versions for non-enums.
You can achieve this using IL Weaving and ExtraConstraints
Allows you to write this code
public class Sample
{
public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
{
}
public void MethodWithEnumConstraint<[EnumConstraint] T>()
{
}
}
What gets compiled
public class Sample
{
public void MethodWithDelegateConstraint<T>() where T: Delegate
{
}
public void MethodWithEnumConstraint<T>() where T: struct, Enum
{
}
}
This doesn't answer the original question, but there is now a method in .NET 4 called Enum.HasFlag which does what you are trying to do in your example
The way I do it is put a struct constraint, then check that T is an enum at runtime. This doesn't eliminate the problem completely, but it does reduce it somewhat
Using your original code, inside the method you can also use reflection to test that T is an enum:
public static class EnumExtension
{
public static bool IsSet<T>( this T input, T matchTo )
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Must be an enum", "input");
}
return (input & matchTo) != 0;
}
}
Here's some code that I just did up that seems to work like you want without having to do anything too crazy. It's not restricted to only enums set as Flags, but there could always be a check put in if need be.
public static class EnumExtensions
{
public static bool ContainsFlag(this Enum source, Enum flag)
{
var sourceValue = ToUInt64(source);
var flagValue = ToUInt64(flag);
return (sourceValue & flagValue) == flagValue;
}
public static bool ContainsAnyFlag(this Enum source, params Enum[] flags)
{
var sourceValue = ToUInt64(source);
foreach (var flag in flags)
{
var flagValue = ToUInt64(flag);
if ((sourceValue & flagValue) == flagValue)
{
return true;
}
}
return false;
}
// found in the Enum class as an internal method
private static ulong ToUInt64(object value)
{
switch (Convert.GetTypeCode(value))
{
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
return (ulong)Convert.ToInt64(value, CultureInfo.InvariantCulture);
case TypeCode.Byte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return Convert.ToUInt64(value, CultureInfo.InvariantCulture);
}
throw new InvalidOperationException("Unknown enum type.");
}
}
if someone needs generic IsSet (created out of box on fly could be improved on), and or string to Enum onfly conversion (which uses EnumConstraint presented below):
public class TestClass
{ }
public struct TestStruct
{ }
public enum TestEnum
{
e1,
e2,
e3
}
public static class TestEnumConstraintExtenssion
{
public static bool IsSet<TEnum>(this TEnum _this, TEnum flag)
where TEnum : struct
{
return (((uint)Convert.ChangeType(_this, typeof(uint))) & ((uint)Convert.ChangeType(flag, typeof(uint)))) == ((uint)Convert.ChangeType(flag, typeof(uint)));
}
//public static TestClass ToTestClass(this string _this)
//{
// // #generates compile error (so no missuse)
// return EnumConstraint.TryParse<TestClass>(_this);
//}
//public static TestStruct ToTestStruct(this string _this)
//{
// // #generates compile error (so no missuse)
// return EnumConstraint.TryParse<TestStruct>(_this);
//}
public static TestEnum ToTestEnum(this string _this)
{
// #enum type works just fine (coding constraint to Enum type)
return EnumConstraint.TryParse<TestEnum>(_this);
}
public static void TestAll()
{
TestEnum t1 = "e3".ToTestEnum();
TestEnum t2 = "e2".ToTestEnum();
TestEnum t3 = "non existing".ToTestEnum(); // default(TestEnum) for non existing
bool b1 = t3.IsSet(TestEnum.e1); // you can ommit type
bool b2 = t3.IsSet<TestEnum>(TestEnum.e2); // you can specify explicite type
TestStruct t;
// #generates compile error (so no missuse)
//bool b3 = t.IsSet<TestEnum>(TestEnum.e1);
}
}
If someone still needs example hot to create Enum coding constraint:
using System;
/// <summary>
/// would be same as EnumConstraint_T<Enum>Parse<EnumType>("Normal"),
/// but writen like this it abuses constrain inheritence on System.Enum.
/// </summary>
public class EnumConstraint : EnumConstraint_T<Enum>
{
}
/// <summary>
/// provides ability to constrain TEnum to System.Enum abusing constrain inheritence
/// </summary>
/// <typeparam name="TClass">should be System.Enum</typeparam>
public abstract class EnumConstraint_T<TClass>
where TClass : class
{
public static TEnum Parse<TEnum>(string value)
where TEnum : TClass
{
return (TEnum)Enum.Parse(typeof(TEnum), value);
}
public static bool TryParse<TEnum>(string value, out TEnum evalue)
where TEnum : struct, TClass // struct is required to ignore non nullable type error
{
evalue = default(TEnum);
return Enum.TryParse<TEnum>(value, out evalue);
}
public static TEnum TryParse<TEnum>(string value, TEnum defaultValue = default(TEnum))
where TEnum : struct, TClass // struct is required to ignore non nullable type error
{
Enum.TryParse<TEnum>(value, out defaultValue);
return defaultValue;
}
public static TEnum Parse<TEnum>(string value, TEnum defaultValue = default(TEnum))
where TEnum : struct, TClass // struct is required to ignore non nullable type error
{
TEnum result;
if (Enum.TryParse<TEnum>(value, out result))
return result;
return defaultValue;
}
public static TEnum Parse<TEnum>(ushort value)
{
return (TEnum)(object)value;
}
public static sbyte to_i1<TEnum>(TEnum value)
{
return (sbyte)(object)Convert.ChangeType(value, typeof(sbyte));
}
public static byte to_u1<TEnum>(TEnum value)
{
return (byte)(object)Convert.ChangeType(value, typeof(byte));
}
public static short to_i2<TEnum>(TEnum value)
{
return (short)(object)Convert.ChangeType(value, typeof(short));
}
public static ushort to_u2<TEnum>(TEnum value)
{
return (ushort)(object)Convert.ChangeType(value, typeof(ushort));
}
public static int to_i4<TEnum>(TEnum value)
{
return (int)(object)Convert.ChangeType(value, typeof(int));
}
public static uint to_u4<TEnum>(TEnum value)
{
return (uint)(object)Convert.ChangeType(value, typeof(uint));
}
}
hope this helps someone.
I just wanted to add Enum as a generic constraint.
While this is just for a tiny helper method using ExtraConstraints is a bit too much overhead for me.
I decided to just just create a struct constraint and add a runtime check for IsEnum. For converting a variable from T to Enum I cast it to object first.
public static Converter<T, string> CreateConverter<T>() where T : struct
{
if (!typeof(T).IsEnum) throw new ArgumentException("Given Type is not an Enum");
return new Converter<T, string>(x => ((Enum)(object)x).GetEnumDescription());
}

Categories