views:

359

answers:

5

I am self-studying a C# reference and it gives the following information:

1.21.4. Declaring Generic Parameters Generic parameters can be introduced in the declaration of classes, structs, interfaces, delegates (see the upcoming "Delegates" section), and methods. Other constructs, such as properties, cannot introduce a generic parameter, but can use a generic parameter. For example, the property Value uses T:

public struct Nullable<T>
{
  public T Value {get;}
}

First, I get an error trying to compile this saying that it must contain a body because it is neither abstract nor extern or that automatic parameters must have both get and set accessors.

Second, assuming it is wrong and I correct it by adding "set;", I cannot seem to format a call to it successfully.

+8  A: 

That is just showing the API of Nullable<T> rather than the implementation. It's not meant to be compiled - System.Nullable<T> is part of the framework, you don't have to implement it yourself.

Jon Skeet
+3  A: 

You appear to be reading "C# 3.0 in a Nutshell". Well, the example is just that - an example. It is only intended to illustrate how the Value property of the Generic Nullable class exposes the generic parameter declared by the containing type.

It isn't meant to be part of a compilable example.

Cerebrus
+2  A: 

I'm not sure if you just picked a bad example for your struct name (since Nullable is a framework struct), but if not, the error is due to the fact that you have no set accessor in your property. Automatic properties (added in C# 3.0) need both a get and set property. So, if you change the code to:

public struct Nullable<T>
{
  public T Value {get; set; }
}

it should work. In this case, the error had nothing to do with generics. To create an instance, you could use:

Nullable<int> i = new Nullable<int>();

This will make it compile. However, as both Jon and Cerebrus has pointed out, it's probably just an example to show the workings of generics.

Razzie
The example was copied from a book directly. I noted that the "set;" was missing. However, they didn't show the call. I was missing the <int> on the left hand side of the equation in my varied attempts to access the method. This answer solved that right on. Thanks!
Rodddgers
A: 

Your question here seems to be about auto-properties, rather than generics.

Auto-properties must have a set accessor, although it doesn't have to have the same visibility as the get:

public T Value { get; private set; }

You can call the set in the constructor:

public Nullable ( T value ) {
    Value = value;
}

Although in this case you're dealing with a struct, and they always have a default (parameterless) constructor - you have to be a bit more careful with structs and auto-properties.

In .net there's already a nullable generic:

Nullable<int> i = GetCounterThatMightBeNull();

int j = 0;
if( i.HasValue )
    j = i.Value;
...

This was added in .Net 2 (at the same time as generics), and while early betas looked like the code above they streamlined it the final version:

//int? is shorthand for Nullable<int>
int? i = GetCounterThatMightBeNull(); 

// ?? is shorthand for the null check
int j = i ?? 0;

//or
if( i == null ) {
    //this works even though Nullable<int> is a struct
}
Keith
A: 

For an automatic property you always need both a getter and setter. Without a getter you could set the value, but nothing could ever retrieve it. Without a setter the value would always be the default because nothing could ever set it:

//tradition 
private T _value; 
public T Value 
{ 
    get 
    {
        return _value;
    }
}
//locally, _value can always be set

//Auto-matically implemented property
public T Value { get; }
//there is never a way to set it

//with this it can be privately set, but is get only to everyone else
public T Value{ get; private set; }
Timothy Carter