Identifyng Generics and Enums in a C# "where" clause

In generics, you can add constraints on the type argument using the where clause
e.g.:
public class List<T> where T: IList…

My question is what should you put in the where clause to filter only
1. nullable types
2. enums

I already look for this in the web and didn't find an answer, so it's not trivial.
For example:

  1. All the following nulllable filters won't pass compilation: where Nullable<Struct>, where Nullable, where Nullable<T>
  2. All the following enum filters won't pass compilation: where System.Enum

Any help will be appreciated.

Thanks,
Busi



Answer this question

Identifyng Generics and Enums in a C# "where" clause

  • kblackwell


  • foobarX

    As per C# spec a constraint can be:

    1) a class type

    2) the class keyword

    3) the struct keyword

    4) an interface type

    5) a type parameter

    6) new()

    As you can see there is nothing that allows you to specify a particular value type (both enums and Nullable<T> are value types). The closest you can get is to use the struct constraint which allows for value types only.

     

     


  • averge joe

    Mike, I should report this answer as an abuse... ;-)
    I got your trick, not sure if I'll use it for this specific purpose, but I'll keep that in mind.

    Thanks a lot!


  • Duncan_

    Hello James,
    thanks for your posts. The last one in the tread seems to fulfill my original request.

    Busi


  • SnakeSV

    Hi Mike,
    Thanks a lot for the quick answer.

    This is quite awkward. I won't be able to use the HasValue property of a nullable type inside a generic method implementation.

    Thanks anyway,
    Busi


  • Giber

    I won't be able to use the HasValue property of a nullable type inside a generic method implementation

    Well, if you are trying to do something like this:

    void DoIt<T>(T t) where T : Nullable {,,,,}

    that could be written as:

    void DoIt<T>(Nullable<T> t) where T : struct { ....}



  • marge_may

    Actually there is a trick that can be done about HasValue but it has some performance implications:

    class Test<T>

    {

    private T data;

    public Test(T data)

    {

    this.data = data;

    }

    public bool IsNull

    {

    get

    {

    // here's the trick: cast data to object and compare to null.

    // casting to object force the value of data to be boxed and boxing a Nullable

    // without value results in null

    // however boxing is expensive because it must allocate a new object on the gc heap (if Nullable

    // has a value, otherwise probably there is no performance penality).

    return ((object)data == null);

    }

    }

    }

    class Program

    {

    static void Main(string[] args)

    {

    Test<int > foo = new Test<int >(2);

    Console.WriteLine(foo.IsNull);

    foo = new Test<int >(null);

    Console.WriteLine(foo.IsNull);

    }

    }


  • faith2006

    Similar results can be achieved without boxing, through overloading:


    bool IsNullable<T>(T t) where T:struct
    {
    return false;
    }
    bool IsNullable<T>(Nullable<T> t) where T:struct
    {
    return true;
    }

    bool IsNullable(object t)
    {
    return true;
    }



  • Identifyng Generics and Enums in a C# "where" clause