Click here to Skip to main content
15,888,321 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I decided one of the enums in my project might benefit from being more intelligent and followed the Microsoft example on the following page:

Microsoft Extended Enum

This is a cut-down version of my code:

public abstract class Enumeration : IComparable
{
    protected Enumeration() {}

    protected Enumeration( int id, string name )
    {
        Id = id;
        Name = name;
    }

    public int Id { get; }

    public string Name { get; }

    public int CompareTo( object other ) => Id.CompareTo( ((Enumeration)other).Id );

    public override string ToString() => Name;

    public static IEnumerable<T> GetAll<T>() where T : Enumeration, new()
    {
        Type type = typeof( T );
        FieldInfo[] fields = type.GetTypeInfo().GetFields( BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly );
        foreach( var info in fields )
        {
            var instance = new T();
            var locatedValue = info.GetValue( instance ) as T;
            if( locatedValue != null )
                yield return locatedValue;
        }
    }
    
    public override bool Equals(object obj)
    {
        if( !( obj is Enumeration otherValue ) ) return false;
        var typeMatches = GetType().Equals(obj.GetType());
        var valueMatches = Id.Equals(otherValue.Id);
        return typeMatches && valueMatches;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}


public class Fruit : Enumeration
{
    public static Fruit Apple = new AppleFruitType();
    public static Fruit Banana = new BananaFruitType();
    public static Fruit Orange = new OrangeFruitType();

    protected Fruit( int id, string name ) : base( id, name ) { }

    private class AppleFruitType : Fruit
    {
        public AppleFruitType() : base( 0, "Apple" ) {}
    }

    private class BananaFruitType : Fruit
    {
        public BananaFruitType() : base( 1, "Banana" ) {}
    }

    private class OrangeFruitType : Fruit
    {
        public OrangeFruitType() : base( 2, "Orange" ) {}
    }
}


public class MainApplication
{
    public void SomeCode()
    {
        // None of these three lines will compile.
        List<Fruit> AllFruits1 = Fruit.GetAll();
        List<Fruit> AllFruits2 = Fruit.GetAll<Fruit>();
        List<Fruit> AllFruits3 = Fruit.GetAll<Enumeration>();
    	List<Fruit> AllFruits4 = Fruit.GetAll().ToList<Fruit>;
    	List<Fruit> AllFruits5 = Fruit.GetAll<Fruit>().ToList<Fruit>;
    	List<Fruit> AllFruits6 = Fruit.GetAll<Enumeration>().ToList<Fruit>;
    }
}


Although the compiler information on why these six lines don't work seems to be clear, I can't figure out what I need to write to get this working.

Can anyone please explain this obvious glaring hole in my language knowledge?

What I have tried:

The examples shown in the above code.
Posted
Updated 21-Aug-18 23:26pm

Fruit must have a parameterless constructor.
Add
C#
public Fruit()
{
}

to your Fruit class and
C#
var AllFruits2 = Fruit.GetAll<Fruit>();

should work.
 
Share this answer
 
Comments
Patrick Skelton 22-Aug-18 5:32am    
That is indeed all that was needed. the compiler told me as such but I didn't add one because I foolishly thought, "If it needed a public parameterless constructor, surely Microsoft's example code would have one."

Now all of the following compile fine:

var AllFruits1 = Fruit.GetAll<fruit>();
IEnumerable<fruit> AllFruits2 = Fruit.GetAll<fruit>();
List<fruit> AllFruits3 = Fruit.GetAll<fruit>().ToList();

Thank you!
To get a specific type e.g. Fruit, you can do this:
C#
IEnumerable<Fruit> AllFruits1 = Enumeration.GetAll<Fruit>();


If you have another extended enum type like CardType:

C#
public abstract class CardType : Enumeration
...


IEnumerable<CardType> AllCardType1 = Enumeration.GetAll<CardType>();
IEnumerable<Fruit> AllFruits1 = Enumeration.GetAll<Fruit>();


Basically the purpose of Enumeration class is that you can easily get your all enum types
 
Share this answer
 
Comments
Patrick Skelton 22-Aug-18 5:35am    
Thanks for the explanation. You did state very clearly something I hadn't quite realised. I chose a different answer as solution because your reply didn't mention the public parameterless constructor that appears to be required. Thank you.
Keviniano Gayo 22-Aug-18 5:56am    
No problem. Public parameter-less by the way is not required, unless you are going to instantiate a class without parameters. Although the compiler will add the default constructor(parameter-less) in the background if you didn't explicitly declare it, if no constructor override in your class declaration.
Patrick Skelton 22-Aug-18 6:02am    
Mmm... I can't get it to work without explicitly adding a public parameter-less constructor. Doesn't the declaration of the protected constructor with parameters remove the default one?
Keviniano Gayo 22-Aug-18 6:50am    
Yes it removed the default parameter-less constructor
Patrick Skelton 22-Aug-18 6:57am    
So don't I need to put it back to get a list of all the enumeration values or is there a better way?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900