4

I would like to declare in a parent abstract class something along the lines of:

  public abstract void RefreshDisplay<TView>(Enum value);

Which would then be implemented in the child class like:

   public override void RefreshDisplay<RxViewModel>(RxViews view)

Where RxViews is an enumeration and "view" a specific value from that enumeration.

The actual view and Enum from which it came will not be known until run-time.

Can this be done? I appreciate the help.

Edit: I may have asked this wrong. The TView is not an enumeration, but rather a view that inherits from ViewModelBase. (I don't see where this is a duplicate question?) Thanks.

Edit: I'm guessing this was fixed in net 4.5. Any ideas how to work around this in net 4.0?

Alan Wayne
  • 5,122
  • 10
  • 52
  • 95
  • 1
    Duplicate of http://stackoverflow.com/questions/1331739/enum-type-constraints-in-c-sharp – Vladimirs Nov 26 '14 at 16:03
  • Why does your first snippet work for you? – Servy Nov 26 '14 at 16:04
  • 1
    Why don´t use two generic types, one for the viewModel and other for the Enum, like this: public abstract void RefreshDisplay(TEnum value) where TEnum : Enum; – lombardo Nov 26 '14 at 16:10
  • @Lombardo Error: "TEnum is a field but is used like a type" ??? Thanks. – Alan Wayne Nov 26 '14 at 16:16
  • @Servy "No suitable method found to override." I do not know how to generalize the child call on RefreshhDisplay in the parent. Thanks. – Alan Wayne Nov 26 '14 at 16:20
  • @Lombardo Can this be done in VS2010? – Alan Wayne Nov 26 '14 at 16:24
  • @Lombardo Umm.. Upon recompile, I now get "Constraint cannot be special class System.Enum" ??? (VS2010). – Alan Wayne Nov 26 '14 at 16:29
  • I'm not sure what you're trying to do, even beyond the enum question. You can't specify the generic type when you're overriding an abstract generic method. – Dax Fohl Nov 26 '14 at 16:38
  • @DaxFohl I have multiple different detail listings being shown in a common scroll viewer. The different lists are based on a specific values from an enumeration. I am trying to generalize the RefreshDisplay() in my viewmodel base so as it can be inherited by the specific views. (If not a good explanation I can give more detail). – Alan Wayne Nov 26 '14 at 16:43
  • 2
    You might use a custom class instead of an enum. The base class could be defined as Views, you inherit it for each TView and provides static instances for each value. – Guillaume Nov 26 '14 at 16:45
  • @Guillaume Could you give a short example? Thanks. – Alan Wayne Nov 26 '14 at 16:48
  • You'll have to make the base class generic on TView and TViewEnum, but you won't be able to operate on them generically because each subclass will have different generic params. So I think you need to rethink your design, which is a whole other question. – Dax Fohl Nov 26 '14 at 16:50
  • @DaxFohl I'm new to this...Any suggestions? Thanks. – Alan Wayne Nov 26 '14 at 17:03
  • @AlanWayne no suggestions - that is not possible right-away (at least so far), have you read first link? – Vladimirs Nov 26 '14 at 17:08
  • 1
    Hard to say without being there. Don't get too carried away with type safety; it can be a good mental exercise to make everything fit but sometimes upcasting and asserting is more readable and pragmatic, and type theory itself has some loose edges anyway. – Dax Fohl Nov 26 '14 at 17:12
  • 2
    Also consider using java-style enums: http://stackoverflow.com/a/469315/171121 – Dax Fohl Nov 26 '14 at 17:17
  • @Vladimirs Yes. Discouraged :( – Alan Wayne Nov 26 '14 at 17:19
  • @DaxFohl I'm thinking this is a good example of what Guillaume meant? Thanks much. – Alan Wayne Nov 26 '14 at 17:27

2 Answers2

12

The constraint type you need to use for generics with an Enum in .NET 4.0 is as follows - note you will need to change your class declaration for this to work correctly:

public abstract class BaseClass<TView, TEnum> 
    where TView: ViewModelBase
    where TEnum : struct,  IComparable, IFormattable, IConvertible
{

    public abstract void RefreshDisplay<TView, TEnum>(TEnum value);
}

You should however also do something similar to the following line in your implementation of the method:

if (!typeof(TEnum).IsEnum) { throw new ArgumentException("TEnum must be an enumerated type"); }

The type check is necessary due to not being 100% sure that it's an Enum (tho' Enum implements all those aspects which is why they are used).

You might want to consider rather making the method virtual and including that in the base method implementation.

Note that this code is adapted from the answer available here : Create Generic method constraining T to an Enum

Community
  • 1
  • 1
toadflakz
  • 7,764
  • 1
  • 27
  • 40
0

You might use a custom class instead of an enum. The base class could be defined as Views, you inherit it for each TView and provides static instances for each value.

public abstract class A
{
    public abstract void RefreshDisplay<TView>(Views<TView> value);
}

public abstract class Views<TView>
{
    internal Views() {} //Used to disallow inheriting from outside, not mandatory...

    //You can add other methods/properties to allow processing in RefreshDisplay method
}

public sealed class RxViews : Views<TView>
{
    private RxViews() {}

    private static readonly RxViews myFirstRxView = new RxViews();
    public static RxViews MyFirstRxView { get { return myFirstRxView; } }
}
Guillaume
  • 12,824
  • 3
  • 40
  • 48