views:

142

answers:

4

given a class definition like:

public class Test<T>
{
    T _value;

    public void Test(T value)
    {
        _value = value;
    }

    public void DoStuff()
    {
        if(_value.HasValue)
        {
            //stuff
        }
    }
 }

I would like to enforce that T is nullable so I can use the class like:

//does stuff
new Test<int?>(3).DoStuff();
//doesn't do stuff
new Test<int?>(null).DoStuff();
A: 

Yes, just use T? or Nullable<T> as type parameter.

Then your sample becomes:

//does stuff
new Test<int>(3).DoStuff();
//doesn't do stuff
new Test<int>(null).DoStuff();
Joaquim Rendeiro
A: 

You could try:-

public class Test<Nullable<T>>
AdamRalph
+7  A: 

You can't enforce that T itself is a nullable value type, no. You can enforce that T is a non-nullable value type, however - and then use T? everywhere in the class.

public class Test<T> where T : struct
{
    T? _value;

    public void Test(T? value)
    {
        _value = value;
    }

    public void DoStuff()
    {
        if(_value.HasValue)
        {
            //stuff
        }
    }
 }

One other peculiarity is that you can't constrain T to be any nullable type including reference types - and likewise you can't constrain T to be any value type including nullable value types. The where T : class constraint only works with classes (including delegate types) and interfaces, and the where T : struct constraint only with non-nullable value types (including enums).

Jon Skeet
On your last paragraph: I guess that's so you can't make a Nullable<Nullable<int>>? Or can you?
Dan Tao
Nope, you can't (just checked). Makes sense to me!
Dan Tao
FYI, in the original design and implementation of nullable types, the language designers considered allowing nullables of nullables, but ultimately decided to outlaw it. However, there is still code in the compiler for dealing with it, since those scenarios do come up in error cases, or when people type in crazy things in the IDE that the semantic analyzer needs to make a best guess at.
Eric Lippert
A: 

Nullable types are essentially derived from the type Nullable<T>. Could you define your interface based upon Nullable<T>?

Martin Peck
No, they're not derived from `Nullable<T>`. They can't be, as `Nullable<T>` is a struct. They're not derived from the `Nullable` class either, which is a static class.
Jon Skeet
True. Bad choice of words on my part. I was basically trying to ask the API couldn't be defined in terms of 'Nullable<T>'. I was struggling to see what stuff would be done in DoStuff() that required a generic type.
Martin Peck