17

Possible Duplicate:
Create Generic method constraining T to an Enum

Is there any reason why we can't do this in C#? And, if possible, how can I do something similar!

What I want :

public class<T> ATag where T : enum {
    [Some code ..]
}

public class<T> classBase where T : enum {
    public IDictionary<T, string> tags { get; set; }
}

So, when it comes the time to call it, I'm sur to get only one of my enum values.

public class AClassUsingTag : classBase<PossibleTags> {
    public void AMethod(){
         this.tags.Add(PossibleTags.Tag1, "Hello World!");
         this.tags.Add(PossibleTags.Tag2, "Hello Android!");
    }
}

public enum PossibleTags {
    Tag1, Tag2, Tag3
}

Error message : "Constraint cannot be special class 'System.Enum'"

Thank you!

Pramod More
  • 1,220
  • 2
  • 22
  • 51
Simon Dugré
  • 17,980
  • 11
  • 57
  • 73
  • 3
    It is not possible. Have a look here for a work around: http://stackoverflow.com/questions/79126/create-generic-method-constraining-t-to-an-enum – Daniel Hilgarth Feb 25 '11 at 17:12
  • 2
    By the way, the specification is delightful and illuminating reading. Every C# programmer should be familiar with it, and it should be your first source when you have a question about the language. cf. 10.1.5, in particular, for this question. – jason Feb 25 '11 at 17:17
  • 1
    @Jason: Yup, and the C# 4 Annotated Spec is particularly wonderful. And I'm not just saying that because I contributed annotations - all the *other* annotations are really interesting :) – Jon Skeet Feb 25 '11 at 18:10
  • @Jon Skeet: I agree, all the annotations are insightful. – jason Feb 25 '11 at 18:24
  • @Jon: Is there a newer version of the C# Annotated Standard book available? I could not find it. – Chris Dunaway Feb 25 '11 at 20:08
  • @Chris: Newer than which version? I was referring to this one: http://www.amazon.com/dp/0321741765 – Jon Skeet Feb 25 '11 at 20:11
  • Oups sorry... my english not realy good so I didn't find any question related to this before asking it. Hum, sorry but thanks for answerin' it! – Simon Dugré Feb 28 '11 at 13:37
  • @Jon: Thanks, I was referring to this one: http://www.amazon.com/dp/0123725119 and that's what I was searching for. – Chris Dunaway Feb 28 '11 at 20:12

3 Answers3

29

You can't do it because the spec says you can't, basically. It's annoying, but that's the way it is. The CLR supports it with no problem. My guess is that when generics were first being designed, the CLR might not have supported it, so it was prohibited in the language too... and either the C# team didn't get the memo about it then being supported, or it was too late too include it. Delegates are similarly annoying.

As for a workaround... have a look at my Unconstrained Melody project. You could use the same approach yourself. I wrote a blog post at the same time, which goes into more details.

DavidG
  • 113,891
  • 12
  • 217
  • 223
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Do you think this sort of issue is likely to be resolved with Roslyn? – Matthew Layton Sep 24 '14 at 14:28
  • @series0ne: It's not in the feature list for C# 6 as far as I'm aware... though it may make it easier to do. (It could be easy to hack the check out of Roslyn, too...) – Jon Skeet Sep 24 '14 at 14:30
  • I was trying a method found [here](https://stackoverflow.com/a/16104/2218697) to convert `string` to `Enum` , One the Comments says to add `where T : struct` for the extension method to work. But why is it necessary ? Is it syntax for [Enum.TryParse](https://msdn.microsoft.com/en-us/library/dd991317(v=vs.110).aspx) ? – Shaiju T Dec 15 '17 at 08:15
  • 1
    @stom: Yes - you can only call `Enum.TryParse` when `TEnum` is known to be a value type due to the constraint on it; if you're calling it from your own generic method, you need the same constraint to ensure that it's a value type. – Jon Skeet Dec 15 '17 at 08:16
  • ok here is a [method](https://pastebin.com/raw/BqkhP4hz) , which has a constraint `where T : int` and `int` is a value type , But I get compile time Error, Why? `'int' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter` – Shaiju T Dec 15 '17 at 08:27
  • 1
    @stom: You should ask a new question at this point, as it's really not relevant to this answer. But basically the compiler is telling you what I'd tell you - that constraint is invalid. (How would it be useful anyway? If `int` is the only type you can use, it's not really generic any more...) – Jon Skeet Dec 15 '17 at 08:30
  • Now possible! Found it at https://stackoverflow.com/a/8086788 – Tobias Knauss May 13 '18 at 10:55
6

it's not possible. But if you are interested in a runtime check you can do

class A<T>
        {
            static A()
            {
                if(!typeof(T).IsEnum)
                {
                    throw new Exception();
                }
            }
        }
Bala R
  • 107,317
  • 23
  • 199
  • 210
0

No I don't believe so. Yes use a design pattern to get around it, have the base class return the type that's allowed, and the derived classes can check for it.

HTH.

Brian Mains
  • 50,520
  • 35
  • 148
  • 257