Extension Method to Get the Values of Any Enum - c#

I've been trying to create an extension method, that would work on any enum, to return its values.
Instead of doing this:
Enum.GetValues(typeof(BiasCode)).Cast<BiasCode>()
It would be nice to do this:
new BiasCode().Values()
It would even be better without new, but that's another issue.
I have a .NET fiddle that has a solution that's close (code shown below). The problem with this code is that the extension method is returning List<int>. I would like to have it return a list of the enum values itself. Returning List<int> isn't terrible; it just means I have to cast the result.
Is it even possible to do this? I tried making the extension method generic, but ran into problems. This is as close as I was able to get:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
foreach (int biasCode in new BiasCode().Values())
{
DisplayEnum((BiasCode)biasCode);
}
}
public static void DisplayEnum(BiasCode biasCode)
{
Console.WriteLine(biasCode);
}
}
public enum BiasCode
{
Unknown,
OC,
MPP
}
public static class EnumExtensions
{
public static List<int> Values(this Enum theEnum)
{
var enumValues = new List<int>();
foreach (int enumValue in Enum.GetValues(theEnum.GetType()))
{
enumValues.Add(enumValue);
}
return enumValues;
}
}

You can return an instance of the appropriate enum type (created using reflection), but its static type cannot be List<EnumType>. That would require EnumType to be a generic type parameter of the method, but then the type would have to be constrained to only enum types and that is not possible in C#.
However, you can get close enough in practice (and add runtime checks to top it off) so you can write a method that works like this:
public static IEnumerable<TEnum> Values<TEnum>()
where TEnum : struct, IComparable, IFormattable, IConvertible
{
var enumType = typeof(TEnum);
// Optional runtime check for completeness
if(!enumType.IsEnum)
{
throw new ArgumentException();
}
return Enum.GetValues(enumType).Cast<TEnum>();
}
which you can invoke with
var values = Values<BiasCode>();
I have made the method return IEnumerable<TEnum> instead of a list for the extra LINQ-y flavor, but you can trivially return a real list with .ToList() on the return value.

You could declare your method like this:
public static List<T> Values<T>() where T : struct
{
var type = typeof(T);
if(!type.IsEnum) return null; // or throw exception
return Enum.GetValues(type).Cast<T>().ToList();
}
Then you can call it
Values<BiasCode>();

I'm wondering if I'm missing something because all of the answers use a generic method as part of the solution. Why not just do something like this?
public static List<Enum> Values(this Enum theEnum)
{
return Enum.GetValues(theEnum.GetType()).Cast<Enum>().ToList();
}
The fiddle is here: https://dotnetfiddle.net/FRDuvD
This way this extension method will only be available to enums. Using the generics approach, the extension method seems to be available to all types:
string someString = "x";
someString.Values();
It would be better not to have Values() available to a string at compile time.

How about this
class Program{
static void Main(string[] args)
{
BiasCode b = BiasCode.MPP;
var these = b.Values().ToList();
//... these contains the actual values as the enum type
}
}
public static class EnumExtensions
{
public static IEnumerable<T> Values<T>(this T theEnum) where T : struct,IComparable, IFormattable, IConvertible
{
var enumValues = new List<T>();
if ( !(theEnum is Enum))
throw new ArgumentException("must me an enum");
return Enum.GetValues(typeof(T)).Cast<T>();
}
}

Since you are looking for the extension method, here it is:
public static class EnumExtensions
{
public static List<T> Values<T>(this T theEnum)
where T : struct, IComparable, IFormattable, IConvertible
{
if (!typeof(T).IsEnum)
throw new InvalidOperationException(string.Format("Type {0} is not enum.", typeof(T).FullName));
return Enum.GetValues(theEnum.GetType()).Cast<T>().ToList();
}
}
EDIT
I will incorporate my comment in Bob's answer here:
So, I think we could all agree that there is no best solution for this, since it is not possible to do a where clause constraint on Enum type. Another solution would be to have a following method signature (as Bob suggested):
public static List<Enum> Values(this Enum theEnum)
What we would do better with this solution is the constraint only on Enum values. However, in comparison to the generic solution, we lose the information about the enum type, on which we are invoking your extension method. So we need to cast it again. And I do not see much difference between this and the approach originally posted in by Bob in his question, where he returns List<int> and needs to cast it back to our enum.
The most elegant solution can be achieved by using Code Contracts with static checking. However it requires usage of the code contracts and it would probably an overkill if they are to be used in this single case. This approach was addressed in the following thread: Using code contracts to make a generic to be of type enum

Extension method to get the values of any enum in C#
Based on solutions above with slightly different approach:
public static class Enum<TEnum> where TEnum : struct, IComparable, IFormattable, IConvertible
{
public static IEnumerable<TEnum> GetAll()
{
var t = typeof(TEnum);
if (!t.IsEnum)
throw new ArgumentException();
return Enum.GetValues(t).Cast<TEnum>();
}
}
Usage
var values = Enum<MyEnum>.GetAll();
Test
public enum Test
{
First,
Second,
Third
}
[TestClass]
public class EnumTests
{
[TestMethod]
public void MyTestMethod()
{
var values = Enum<Test>.GetAll();
Assert.AreEqual(3, values.Count());
}
}
.net c# enum extension

Related

Restrict an IList<T> extension method to exclude Arrays

Supposing I create an extension method for IList but this extension is part of a library potentially used across many projects. I do not have the control on how it is called.
Is there a way to prevent an Array to call an IList<T> extension method at compile time? This to avoid any misuse, the caller cannot guess the exact implementation, if the .Add() method would be called or only the indexer for example.
I could not find a possible solution with generic constraint type.
So far the only possibility left would be to restrict the extension method to List<T> directly.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var array = new[]{"Hello"};
array.DummyInsert("World"); // this will crash at run time
}
}
public static class DummyExtension
{
public static T DummyInsert<T>(this IList<T> list, T insertValue)
{
list.Add(insertValue);
return insertValue;
}
}
You can add your extension method to List<T> not on IList<T>
I Agree with Ed Plunkett, use a ReadOnlyCollection<T>. But you can do it like this. It's your foot, you can shoot it if you want.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var array = new[]{"Hello"};
var world = array.Insert("World"); // this will crash at run time
Console.WriteLine(array.Length);
}
}
public static class DummyExtension
{
public static T Insert<T>(this IList<T> list, T insertValue)
{
Console.WriteLine("WrongInsert");
list.Add(insertValue);
return insertValue;
}
[Obsolete("If want a compile time exception you can do this too.", true)]
public static T Insert<T>(this T[] list, T insertValue)
{
Console.WriteLine("RightInsert");
return insertValue;
}
}
This prints
RightInsert
1
https://dotnetfiddle.net/i6p1Z5
EDIT:
It was pointed out in the comments below that this won't work if your array has been cast to an IList<T> either explicitly or implicitly. There is nothing wrong with using List<T> here instead of IList<T> unless you are trying to actually extend the IList<T>. In that case extend it in a way that makes sense for all IList<T>. I just wanted to show that yes, what you ask can be done. With great power comes great responsibility.
The run-time issue is because of the fact that the Array is of fixed length hence when you try to insert an element into it you end up with an exception. Instead you can have your own extension method for case Array and handle the insertion accordingly.
public class Program
{
public static void Main()
{
var array = new[] { "Hello" };
array = array.Insert("World");
}
}
public static class DummyExtension
{
public static T Insert<T>(this IList<T> list, T insertValue)
{
list.Add(insertValue);
return insertValue;
}
public static T[] Insert<T>(this T[] list, T insertValue)
{
var destArray = new T[list.Length + 1];
Array.Copy(list, destArray, list.Length);
destArray[destArray.Length - 1] = insertValue;
return destArray;
}
}
Well I agree it may be a crude way, but it will work for your case.

How can I add an extension method to many classes?

I have about 1000 classes in which i need to count the number of properties of. I have the following code:
public static int NumberOfProperties()
{
Type type = typeof(C507);
return type.GetProperties().Count();
}
I could copy and paste this in to each class changing the typeof parameter but this seems a bit tedious.
Is there anyway to make an extensions method to do this by just doing var nop = C507.NumberOfProperties();?
Just to add to the answers suggesting an extension for object for completeness: you can also consider implementing an extension only for Type:
public static int GetPropertyCount(this Type t)
{
return t.GetProperties().Length;
}
and use it like this:
typeof(C507).GetPropertyCount();
The advantage is that you can get the number of properties directly from the type and do not have to create an instance first.
So you can write an extension method that uses object or one that uses type.
public static class ObjectExtensions
{
public static int GetNumberOfProperties(this object value)
{
return value.GetType().GetProperties().Count();
}
public static int GetNumberOfProperties(this Type value)
{
return value.GetProperties().Count();
}
}
Usage:
new C507().GetNumberOfProperties();
typeof(C507).GetNumberOfProperties();
However, you explicitly state two things:
I could copy and paste this in to each class changing the typeof
I have about 1000 classes
You'll likely not want to instantiate a 1000 classes or copy and paste typeof() 1000 times
In this case, you will want to read them all from the Assembly.
So something like:
typeof(SomeClass).Assembly.GetTypes().Select(x => new
{
x.Name,
PropertyCount = x.GetType().GetProperties().Count()
});
Where SomeClass is a class (doesn't matter which) where all the classes reside.
I just simply select them out into an anonymous object which contains the Types name and property count.
This:
typeof(SomeClass).Assembly
Is just a convience way to get the assembly. There are other ways.
Assembly.GetAssembly(typeof(Program)).GetTypes()
Assembly.GetCallingAssembly().GetTypes()
Assembly.Load("Some Assemble Ref").GetTypes()
You can do allsorts with the types that you find. If you select out the Type itself, you can instantiate it later using Activator.CreateInstance (if it has parameterless constuctor). You can also auto fill the properties with reflection as well.
It is impossible to have a static extension method as you imagine it. That being said, it would be possible to create a generic method in a helper class as follows.
public static int NumberOfProperties<T>()
{
Type type = typeof(T);
return type.GetProperties().Count();
}
Given a type SomeType it could be called as int n = NumberOfProperties<SomeType>().
You could make an extension method on object like this:
public static int PropertyCount(this object thing)
{
return thing.GetType().GetProperties().Count();
}
And use it on any object you like:
var x = "some string";
var numProps = x.PropertyCount();
If you want to have an extension method on object:
public static ObjectExtensions
{
public static int NumberOfProperties(this object value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetType().GetProperties().Length;
}
}
...
C507 myObj = new C507();
// How many properties does myObj instance have?
int propCount = myObj.NumberOfProperties();
If you want to have an extesnion method on Type:
public static TypeExtensions
{
public static int NumberOfProperties(this Type value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetProperties().Length;
}
}
...
// How many properties does C507 type have?
int propCount = typeof(C507).NumberOfProperties();
There are a couple of ways to do this that are variations of the same thing.
You can pass the Type as an argument to a method:
public static class Helper {
public static int NumberOfProperties(Type type)
{
return type.GetProperties().Count();
}
}
Which you would call like this:
// Imagine you have a class called MyClass
var result = Helper.NumberOfProperties(typeof(MyClass));
You use use the generic system in C# to make the syntax a little cleaner. That would look like this:
public static class Helper {
// Notice the argument was removed and
// the use of the "generic" syntax <T>
public static int NumberOfProperties<T>()
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
And you would call it like this:
var result = Helper.NumberOfProperties<MyClass>();
You could also use "Extensions" which allow you to call it as if it was a method that belonged to your classes.
public static class Helper {
// notice the `this` keyword before the parameter
// this is what tells C# that this is an extension method
public static int NumberOfProperties<T>(this T #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
This will allow you to call the method like this:
var instance = new MyClass();
var result = instance.NumberOfProperties();
In this example I used the generic syntax so that it applies to any type of object. If you wanted to limit it to only objects that inherit from a specific interface or base class you would just change it from using the generic syntax to using the base class/interface. Like this:
public static class Helper {
// notice the type got changed from a generic <T>
// to specifying the exact class you want to "extend"
public static int NumberOfProperties(this MyBaseClass #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
As #rené-vogt mentioned you can also create the extension method so that it extends the type Type instead. See his answer in this thread: https://stackoverflow.com/a/38455233/984780
You can make a generic extension method which can apply to all types:
public static int PropertyCount<T>(this T obj)
{
return typeof(T).GetProperties().Length;
}
This will apply to all types including value types (I.E. structs) which applying to object will not. Thanks to piedar for pointing out my mistake here, applying to object does still add this extension method to value types.
If your classed can implement an interface, then you can extend that interface.
public interface IExtensible {
}
class C507 : IExtensible {
}
public static int NumberOfProperties(this IExtensible extensible)
{
Type type = extensible.GetType();
return type.GetProperties().Count();
}
That being said, having hundreds of (generated?) classes looks like a bad solution to begin with.

How can I define a generic extension method

I am trying to define an extension method that can return an object of a type defined by the call.
Desired Use: Cat acat = guy.GiveMeYourPet<Cat>();
Attempted implementation
I have no trouble defining generic methods like this:
public static T GiveMeYourPet<T>(Person a) { ... }
Cat acat = GiveMeYourPet<Cat>(guy);
or extension methods like this:
public static Cat GiveMeYourPetCat<P>(this P self) where P : Person, ... { ... }
Cat acat = guy.GiveMeYourPetCat();
But when I try to do what I really want:
public static T GiveMeYourPet<T, P>(this P self) where P : Person, ... { ... }
Cat acat = guy.GiveMeYourPet<Cat>();
The compiler expects GiveMeYourPet() to receive 2 type arguments (even though one is implicitly provided by calling the extension method on the object guy.
What can I do to make this work?
Note that I've also tried reversing the order in which the parameters are defined, but nothing changes:
public static T GiveMeYourPet<P, T>(this P self)
The following call also does not work, because you cannot have a method call in the type specifiation:
Cat acat = guy.GiveMeYourPet<guy.GetType(), Cat>();
The C# compiler type inference is not as sophisticated as you might hope. You have to explicitly specify both types in such a method:
void Main()
{
int i = 0;
bool b = i.GiveMeYourPet<bool, int>();
}
public static class MyExtensions
{
public static T GiveMeYourPet<T, P>(this P self)
{
return default(T);
}
}
If you want to avoid specifying both explicitly (and I wouldn't blame you), you might try to change your method to something like:
public static T GiveMeYourPet<T>(this IPetOwner self)
(with this interface, you shouldn't even need to know what the real type is; if you do, use as or is) Or even:
public static T GiveMeYourPet<T>(this object self)
(and use as or is)
If that's not an option, and the real type of guy (in your example) is not statically known (e.g. you just have him as an object), you'll probably have to use reflection, e.g.:
MethodInfo method = typeof(MyExtensions).GetMethod("GiveMeYourPet");
MethodInfo generic = method.MakeGenericMethod(typeof(Pet), guy.GetType());
generic.Invoke(guy, null);
If something like guy.GiveMeYour.Pet<Cat>(); would work you can build 2 levels similar to code:
public class GiveMeYourBuilder<P>
{
public P Me {get;set;}
public T Pet<T>() : where T: new()
{ return new T();}
}
public static PetExtensions
{
public GiveMeYourBuilder<P>(this P me)
{
return new GiveMeYourBuilder<P> { Me = me;}
}
}
You can't partially specify generic arguments, either they are all inferred or you have to specify them all. In this case, the closest you can get is probably to return an intermediate object which carries the generic Person type the extension method is called on, and define your Get methods on that:
public class GiveContext<T> where T : Person
{
public P MeYourPet<P>() where P : Pet
{
return default(P);
}
}
public static GiveContext<T> Give<T>(this T person) where T : Person
{
return new GiveContext<T>();
}
which you can use like:
var p = new Person();
Cat c = p.Give().MeYourPet<Cat>();
You can't do this, unfortunately. If the compiler can't figure them all out, you need to type out all the type arguments. The C# compiler isn't that smart. dynamic can help though:
public static T GiveMeYourPet<T>(this dynamic self)
{
//in here check that self meets your constraints using is, as, etc.
}

Why can I not "see" this enum extension method?

Why cannot I see this enum extension method? (I think I'm going crazy).
File1.cs
namespace Ns1
{
public enum Website : int
{
Website1 = 0,
Website2
}
}
File2.cs
using Ns1;
namespace Ns2
{
public class MyType : RequestHandler<Request, Response>
{
public override Response Handle(Request request, CRequest cRequest)
{
//does not compile, cannot "see" ToDictionary
var websites = Website.ToDictionary<int>();
return null;
}
}
//converts enum to dictionary of values
public static class EnumExtensions
{
public static IDictionary ToDictionary<TEnumValueType>(this Enum e)
{
if(typeof(TEnumValueType).FullName != Enum.GetUnderlyingType(e.GetType()).FullName) throw new ArgumentException("Invalid type specified.");
return Enum.GetValues(e.GetType())
.Cast<object>()
.ToDictionary(key => Enum.GetName(e.GetType(), key),
value => (TEnumValueType) value);
}
}
}
You are trying to call the extension method as a static method on the type rather than as an instance method on an object of that type. This usage of extension methods is not supported.
If you have an instance then the extension method is found:
Website website = Website.Website1;
var websites = website.ToDictionary<int>();
this Enum e refers to an enum instance, whereas Website is actually an enum class type.
Extension methods are just syntactic sugar and they only work with instances and not with the type. So you must call an extension method on an instance of type Website and not on the type itself, as mentioned by Mark.
For your information, In addition to what Mark said, The code gets converted as below upon compilation.
//Your code
Website website = new Website();
var websites = website.ToDictionary<int>();
//After compilation.
Website website = new Website();
var websites = EnumExtensions.ToDictionary<int>(website);
An improved version of the Extension method would be to extend the type Website only and not the Enum.
//converts enum to dictionary of values
public static class EnumExtensions
{
public static IDictionary ToDictionary<TEnumValueType>(this Website e)
{
if(typeof(TEnumValueType).FullName != Enum.GetUnderlyingType(e.GetType()).FullName) throw new ArgumentException("Invalid type specified.");
return Enum.GetValues(e.GetType())
.Cast<object>()
.ToDictionary(key => Enum.GetName(e.GetType(), key),
value => (TEnumValueType) value);
}
}
You need to change the signature of your extension method to use your enum, rather than the Enum type itself. That is, change Enum to Website in your extension method signature:
public static IDictionary ToDictionary<TEnumValueType>(this Website enum, ...)

Behaviour to simulate an enum implementing an interface

Say I have an enum something like:
enum OrderStatus
{
AwaitingAuthorization,
InProduction,
AwaitingDespatch
}
I've also created an extension method on my enum to tidy up the displayed values in the UI, so I have something like:
public static string ToDisplayString(this OrderStatus status)
{
switch (status)
{
case Status.AwaitingAuthorization:
return "Awaiting Authorization";
case Status.InProduction:
return "Item in Production";
... etc
}
}
Inspired by the excellent post here, I want to bind my enums to a SelectList with an extension method:
public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
however, to use the DisplayString values in the UI drop down I'd need to add a constraint along the lines of
: where TEnum has extension ToDisplayString
Obviously none of this is going to work at all with the current approach, unless there's some clever trick I don't know about.
Does anyone have any ideas about how I might be able to implement something like this?
Is there a compelling reason to use an enum here?
When you start jumping through crazy hoops to use enums, it might be time to use a class.
public class OrderStatus
{
OrderStatus(string display) { this.display = display; }
string display;
public override string ToString(){ return display; }
public static readonly OrderStatus AwaitingAuthorization
= new OrderStatus("Awaiting Authorization");
public static readonly OrderStatus InProduction
= new OrderStatus("Item in Production");
public static readonly OrderStatus AwaitingDispatch
= new OrderStatus("Awaiting Dispatch");
}
You consume it the same as an enum:
public void AuthorizeAndSendToProduction(Order order, ProductionQueue queue)
{
if(order.Status != OrderStatus.AwaitingAuthorization)
{
Console.WriteLine("This order is not awaiting authorization!");
return;
}
order.Status = OrderStatus.InProduction;
queue.Enqueue(order);
}
The string representation is built-in, and all you need is ToString().
Of course, you can use the DisplayAttribute to annotate your Enums.
enum OrderStatus
{
[Display(Description="Long Desc", Name="Awaiting Authorization", ShortName="Wait Auth")]
AwaitingAuthorization,
[Display(Description="...", Name="...", ShortName="...")]
InProduction,
[Display(Description="...", Name="...", ShortName="...")]
AwaitingDespatch
}
You can also opt to create an extension method taking any enumeration value and returning its display name based on the attribute set to it to tidy up the displayed values in the UI, as follows:
public static class EnumExtensions
{
public static string ToName(this Enum enumValue)
{
var displayAttribute = enumValue.GetType()
.GetMember(enumValue.ToString())[0]
.GetCustomAttributes(false)
.Select(a => a as DisplayAttribute)
.FirstOrDefault();
return displayAttribute?.Name ?? enumValue.ToString();
}
}
With
public enum Test
{
[Display(Name="AAA")]
a,
b
}
Code:
Console.WriteLine(Test.a.ToName());
Console.WriteLine(Test.b.ToName());
Results
AAA
b
I want to bind my enums to a SelectList with an extension method:
For type safety, I wouldn't use an extension methods, but instead a static class that deals with the Enum type:
Pre C# 7.3 version. Since Enum is not a valid type constraint prior to 7.3 (and it would cause a compile-time exception), you'll end up by considering that enums are value types and they implement some interfaces, in order to restrict the type parameter as close to Enum as possible.
public static class Enums<TEnum> where TEnum : struct, IComparable, IFormattable, IConvertible
{
static Enums()
{
if (!typeof(TEnum).IsEnum)
{
throw new InvalidOperationException();
}
}
}
C# 7.3+ version, with compile time checking... yay!
public static class Enums<TEnum> where TEnum : Enum
{
}
GetValues Method for the class:
public static IEnumerable<TEnum> GetValues(bool includeFirst)
{
var result = ((TEnum[])Enum.GetValues(typeof(TEnum))).ToList();
if (!includeZero)
result = result.Where(r => r != default).ToList();
return result;
}
If you follow Enum Guidelines and include the Default (zero) value, we can ignore it (sometimes we want to display the value like "None Selected" and sometimes we don't "Invalid Selection").
Then we can add another method:
public static IEnumerable<string> GetNames(bool includeFirst)
{
var result = GetValue(includeFirst)
.Select(v => v.ToName())
.ToList();
return result;
}
Instead of using "ToDisplayString", simply override ToString() of your enum. So if an enum overrides it it will take it, otherwise it will take the default ToString behavior (in ToSelectList).
If you just need to use relatively tiny enumerate classes that have no more than an explicit casting operator, ToString and do not take other usability for the special ones about enum on System and its derived namespaces, then the following example could be a solution:
namespace MyNamespace {
public abstract class EnumerateClass<Type, InheritingClass> : IEquatable<InheritingClass>
where Type : IEquatable<Type>
where InheritingClass : EnumerateClass<Type, InheritingClass> {
internal readonly Type Identifier;
protected EnumerateClass (Type identifier) {
this.Identifier = identifier;
}
public bool Equals(InheritingClass obj)
=> this.Identifier.Equals(obj.Identifier);
public static explicit operator Type(EnumerateClass<Type, InheritingClass> obj)
=> obj.Identifier;
}
public sealed class MyNumber : EnumerateClass<int, MyNumber> {
private MyNumber(int identifier) : base(identifier) { }
public static readonly MyNumber None = new Number(0);
public static readonly MyNumber One = new Number(1);
public static readonly MyNumber Two = new Number(2);
...
public override string ToString() {
switch (this.Identifier) {
case 0: return "None";
case 1: return "One";
case 2: return "Two";
...
}
}
}
}
You could do this:
public static string ToOrderStatusDisplayString(this Enum status)
{
switch ((OrderStatus)status)
{
...
}
}
Then restrict TEnum to Enum: where TEnum : System.Enum
Of course, that way you get a bunch of methods on the Enum itself and lose type safety.

Categories

Resources