within class property cannot set embedded struct's property

J

John A Grandy

I can't figure out why this won't compile :

Error 1 Cannot modify the return value of
'System.Nullable<ClassLibrary1.MyStruct>.Value' because it is not a variable
D:\d4\ClassLibrary1\Class1.cs 41 20 ClassLibrary1



using System;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary1
{

struct MyStruct
{
private bool _whacko;

public bool Whacko
{
get{ return _whacko; }
set { _whacko = value; }
}
}


class MyClass
{
private MyStruct? _myStruct;

public bool Whacko
{
get
{
if ( !_myStruct.HasValue)
{
return false;
}
else
{
return _myStruct.Value.Whacko;
}
}
set
{
if ( _myStruct.HasValue)
{
_myStruct.Value.Whacko = value;
}
}
}
}

}



Error 1 Cannot modify the return value of
'System.Nullable<ClassLibrary1.MyStruct>.Value' because it is not a variable
D:\d4\ClassLibrary1\Class1.cs 41 20 ClassLibrary1
 
A

Arne Vajhøj

John said:
namespace ClassLibrary1
{
struct MyStruct
{
private bool _whacko;

public bool Whacko
{
get{ return _whacko; }
set { _whacko = value; }
}
}
class MyClass
{
private MyStruct? _myStruct;
public bool Whacko
{
get
{
if ( !_myStruct.HasValue)
{
return false;
}
else
{
return _myStruct.Value.Whacko;
}
}
set
{
if ( _myStruct.HasValue)
{
_myStruct.Value.Whacko = value;
}
}
}
}

}

Error 1 Cannot modify the return value of
'System.Nullable<ClassLibrary1.MyStruct>.Value' because it is not a variable
D:\d4\ClassLibrary1\Class1.cs 41 20 ClassLibrary1

Nullable Value is a get only property.

If .NET 3.5 / C# 3.0 replace:

_myStruct.Value.Whacko = value;

with:

_myStruct = new MyStruct{Whacko=value};

(you can do the same in earlier versions - you just need to type
a little bit more)

Arne
 
P

Peter Duniho

I can't figure out why this won't compile :

Error 1 Cannot modify the return value of
'System.Nullable<ClassLibrary1.MyStruct>.Value' because it is not a
variable
D:\d4\ClassLibrary1\Class1.cs 41 20 ClassLibrary1

Note that the reason this is happening is because you're mutating a struct
(value type). In general, structs should be immutable; the compiler is
pretty good about producing a warning or error if you use a struct
incorrectly, but there are still places you might overlook such an attempt.

In cases like this, where your struct is embedded in something else, the
only correct way to modify the struct is to create a whole new instance of
the struct and then copy that into the embedded location. For example,
you would have to do the same kind of fix Arne's suggested if you were
using your struct as a value in a List<T> or Dictionary<TKey, TValue>.

If you have a data structure with mutable members, usually it's better to
just go ahead and make it a class. That will fit better with the
semantics of modification of instances of the type.

Pete
 
J

John A Grandy

Not sure I understand.

The following compiles fine :

using System;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary1
{

struct MyStruct
{
private bool _whacko;

public bool Whacko
{
get { return _whacko; }
set { _whacko = value; }
}
}


class MyClass
{
private MyStruct _myStruct;

public bool Whacko
{
get
{
return _myStruct.Whacko;
}
set
{
_myStruct.Whacko = value;
}
}
}

}


Why would using an embedded

MyStruct _myStruct

work, but using an embedded

MyStruct? _myStruct

not work ?
 
P

Peter Duniho

Not sure I understand.

The following compiles fine :

using System;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary1
{

struct MyStruct
{
private bool _whacko;

public bool Whacko
{
get { return _whacko; }
set { _whacko = value; }
}
}


class MyClass
{
private MyStruct _myStruct;

public bool Whacko
{
get
{
return _myStruct.Whacko;
}
set
{
_myStruct.Whacko = value;
}
}
}

}


Why would using an embedded

MyStruct _myStruct

work, but using an embedded

MyStruct? _myStruct

not work ?

Sorry if my use of the word "embedded" was vague. In your second example,
there is nothing "embedded" in the way that I meant. The MyStruct is
exposed as a bare variable, "_myStruct". You can directly access the
members of that variable. But when you have a Nullable<MyStruct> as your
member field for the "MyClass" class, now your "MyStruct" is embedded in
the Nullable<MyStruct> variable, only exposed as the Value property. You
no longer have direct access to the variable storing the value; you
receive a copy of it when you access the property (properties get and set
values; they are not variables themselves).

If you don't understand what the difference between a value type and a
reference type is, nor the specifics of how value types work, it can be
difficult to understand why this doesn't work. So you really should start
with the MSDN documentation on the topics of C# value types, if you
haven't already studied that yet.

Once you understand value types, and in particular the fact that value
types are copied, not referenced, it should become clear that when you
retrieve the value of the property Nullable<MyStruct>.Value, you are
getting a copy of the MyStruct in question, not the original MyStruct
contained within the Nullable<MyStruct> variable. Even if the compiler
let you modify the "Whacko" property from that copied MyStruct, it
wouldn't do any good; you'd be modifying a copy, not the actual one stored
in the Nullable<MyStruct> variable.

I hope that sufficiently clarified the point. If not, please feel free to
point out what's still confusing and I'll make another try. :)

Pete
 
J

John A Grandy

Heh ...

What is confusing me is not the difference between reference types and value
types.

What is confusing me is why Microsoft implemented Nullable<some struct type>
in this manner. It seems to elmininate much of the usefuleness of nullable
structs.

My reason for using Nullable<MyStruct> was because in some of my constructor
overloads for MyClass I do not with to initialize _myStruct.

If my struct variable is initialized I would like to work with the struct in
the manner normally available to me , which includes changes private fields
via set property accessors.
 
B

Ben Voigt [C++ MVP]

John said:
Heh ...

What is confusing me is not the difference between reference types
and value types.

What is confusing me is why Microsoft implemented Nullable<some
struct type> in this manner. It seems to elmininate much of the
usefuleness of nullable structs.


My reason for using Nullable<MyStruct> was because in some of my
constructor overloads for MyClass I do not with to initialize
_myStruct.

You could always just not initialize it, and either recognize that 0 means
not initialized, or have your own "bool myStructHasValue" member variable.
 
P

Peter Duniho

Heh ...

What is confusing me is not the difference between reference types and
value
types.

Since this issue is a fundamental consequence of the intersection of the
design goal of Nullable<T> and the way that value types work, it's hard
for me to see how you can say you _fully_ understand the difference
between reference types and value types, and yet not understand why
Nullable said:
What is confusing me is why Microsoft implemented Nullable<some struct
type>
in this manner. It seems to elmininate much of the usefuleness of
nullable
structs.

How else would they have implemented it? The only other option I see is
for them to have exposed the embedded T as a public field. But a) public
fields should be avoided, and b) as a public field, there'd no way to
prevent code from trying to retrieve the value when the Nullable<T> is
"null". It's the abstraction of the property that provides exactly the
useful semantics that Nullable said:
My reason for using Nullable<MyStruct> was because in some of my
constructor
overloads for MyClass I do not with to initialize _myStruct.

If my struct variable is initialized I would like to work with the
struct in
the manner normally available to me , which includes changes private
fields
via set property accessors.

You can still change the private field via the property. You just have to
remember to do it to a local copy of the value type you have access to,
and then copy the value of that value type back into your
Nullable<MyStruct> variable.

Pete
 
J

John A Grandy

Heh ...
Since this issue is a fundamental consequence of the intersection of the
design goal of Nullable<T> and the way that value types work, it's hard
for me to see how you can say you _fully_ understand the difference
between reference types and value types, and yet not understand why
Nullable<T> works the way it does.

I think I understand reference and value types just fine. My issue is with
pragmatism in the language. As it stands , Nullable<some struct type> is
not very pragmatic.

How else would they have implemented it? The only other option I see is
for them to have exposed the embedded T as a public field. But a) public
fields should be avoided, and b) as a public field, there'd no way to
prevent code from trying to retrieve the value when the Nullable<T> is
"null". It's the abstraction of the property that provides exactly the
useful semantics that Nullable<T> offers.

???

With the existing implementation of Nullable<T> , there's no way to prevent
code from attempting to retrieve a non-existent value :

int? nullableInt = null;

int oops = nullableInt.Value;

// compiles but throws InvalidOperationException : Nullable object must have
a value.

You can still change the private field via the property. You just have to
remember to do it to a local copy of the value type you have access to,
and then copy the value of that value type back into your
Nullable<MyStruct> variable.

Heh , I figured that out before I made my first post on this subject. But
it's rather inconvenient and verbose code. Imagine having to do the
following for dozens of setters :


set
{
if ( _myStruct.HasValue )
{
MyStruct myStructLocal = _myStruct.Value;
myStructLocal.Whacko = value;
_myStruct = myStructLocal;
}
}


Why can't C# just do this for you behind the scenes ?

You type :

_myStruct.Value.Whacko = value;

and C# either throws a runtime error if _myStruct doesn't have a value , or
if it does, then automagically make a copy of the MyStruct instance , assign
value to the Whacko property of the copy, and then assign the copy back to
_myStruct.


The following compiles :

int? nullableInt = 777;
int cool = nullableInt.Value;
nullableInt = null;
int notCool = nullableInt.Value; // throws InvalidOperationException :
Nullable object must have a value.

Why can't it work that way for Nullable<struct> ?
 
P

Peter Duniho

I think I understand reference and value types just fine. My issue is
with
pragmatism in the language. As it stands , Nullable<some struct type> is
not very pragmatic.

With the existing implementation of Nullable<T> , there's no way to
prevent
code from attempting to retrieve a non-existent value :

int? nullableInt = null;

int oops = nullableInt.Value;

// compiles but throws InvalidOperationException : Nullable object must
have
a value.

How is the exception not "preventing code from attempting to retrieve a
non-existent value"? Seems to me, that's exactly what it's doing.

The problem is that if you have a public field instead of a property, and
you do this:

int? nullableInt = null;

int oops = nullableInt.Value;

No exception is thrown. Instead, "oops" gets the value 0.

Again, show me the implementation of Nullable<T> you'd find preferable,
but in which the same "can't access a non-existent value" semantics are
preserved.
Heh , I figured that out before I made my first post on this subject.
But
it's rather inconvenient and verbose code. Imagine having to do the
following for dozens of setters :


set
{
if ( _myStruct.HasValue )
{
MyStruct myStructLocal = _myStruct.Value;
myStructLocal.Whacko = value;
_myStruct = myStructLocal;
}
}

Personally, the whole approach has "wrong, wrong wrong" written all over
it as far as I'm concerned. A setter that fails silently if the value is
not stored? Implementing storage for a property value _inside_ some
nullable object? I would try my hardest to not even have a single
property setter that looked like that, never mind dozens.

But for the sake of argument, let's assume this is exactly the right
design to use. Even so, the code really isn't that verbose, and you can
easily refactor the types involved to make it more concise if you like
(for example, to support the usage Arne suggested, or something similar).
Why can't C# just do this for you behind the scenes ?

Because it has to follow its own rules.
You type :

_myStruct.Value.Whacko = value;

and C# either throws a runtime error if _myStruct doesn't have a value ,
or
if it does, then automagically make a copy of the MyStruct instance ,
assign
value to the Whacko property of the copy, and then assign the copy back
to
_myStruct.

Because that would basically turn your value type into a reference type.
A primary feature of value types is that they are _copied_. If you could
typographically "get" a value type, then modify a member of that value
type and have the results automatically copied back to the original
storage of the value type, then you're just making the value type work
just like a reference type, but inefficiently.

If you want to be able to mutate off a member of a nullable value, use a
type that is inherently nullable in the first place, rather than one that
needs to be wrapped in a whole other type. That is, use a class. If you
don't like the semantics of a struct, you shouldn't be using one.
The following compiles :

int? nullableInt = 777;
int cool = nullableInt.Value;
nullableInt = null;
int notCool = nullableInt.Value; // throws InvalidOperationException
: Nullable object must have a value.

Why can't it work that way for Nullable<struct> ?

It does. Nullable<MyStruct> works exactly the same way your example that
uses Nullable<int> does:

MyStruct? nullableStruct = new MyStruct { Whacko = true };
MyStruct cool = nullableStruct.Value;
nullableStruct = null;
MyStruct cool = nullableStruct.Value; // throws
InvalidOperationException

Pete
 
J

John A Grandy

How is the exception not "preventing code from attempting to retrieve a
non-existent value"? Seems to me, that's exactly what it's doing.

Your point was that if we implement Nullable<struct>.Value as a public field
then people could write code that accessed it even when it was null with no
compile time error.

I was just pointing out that we already have that problem for Nullable<T> in
general, so your point is invalid.


Personally, the whole approach has "wrong, wrong wrong" written all over
it as far as I'm concerned. A setter that fails silently if the value is
not stored? Implementing storage for a property value _inside_ some
nullable object? I would try my hardest to not even have a single
property setter that looked like that, never mind dozens.

But for the sake of argument, let's assume this is exactly the right
design to use. Even so, the code really isn't that verbose, and you can
easily refactor the types involved to make it more concise if you like
(for example, to support the usage Arne suggested, or something similar).

I think it's pretty obvious I just left out throwing exception if
_myStruct.HasValue == false.

The point is not theoretically perfect code , the point is pragmatism. In
the real world people must use code written by others that for various very
good reasons ( such as time/resources, in-production risk, organizational ,
etc. ) is not possible to refactor. Pragmatically, all I want to do is
"bubble up" a pre-existing structs properties to a containing class. And
this could extend up into another containing class.

Newsgroup discussions are great for learning to write theoretically perfect
code , but this doesn't always work to be possible in the real world.

Because it has to follow its own rules.


Because that would basically turn your value type into a reference type.
A primary feature of value types is that they are _copied_. If you could
typographically "get" a value type, then modify a member of that value
type and have the results automatically copied back to the original
storage of the value type, then you're just making the value type work
just like a reference type, but inefficiently.

If you want to be able to mutate off a member of a nullable value, use a
type that is inherently nullable in the first place, rather than one that
needs to be wrapped in a whole other type. That is, use a class. If you
don't like the semantics of a struct, you shouldn't be using one.

It would just be a bit of understood magic. There's no danger. If

_myStruct.Value.Whacko = value;

did not modify the embedded structs privateWhacko field , then what else
would it be doing ?

Various loosely typed languages allow flexibility in operators that is not
atomically rule-based ( i.e. must be understood ).
 
P

Peter Duniho

[...]
I was just pointing out that we already have that problem for
Nullable<T> in
general, so your point is invalid.

No. The point you invented by putting words in my mouth is invalid. I
never wrote anything at all about a "compile time error" and the point I
made still stands.
[...]
It would just be a bit of understood magic. There's no danger. If

_myStruct.Value.Whacko = value;

did not modify the embedded structs privateWhacko field , then what else
would it be doing ?

It would be modifying the instance of MyStruct actually returned by the
Value property.

Once again: VALUE TYPES ARE ALWAYS COPIED. If you return one, you get a
COPY of the original. That's THE WHOLE POINT of value types.

What you want here are reference types semantics. You should not be using
a value type in the first place.
Various loosely typed languages allow flexibility in operators that is
not
atomically rule-based ( i.e. must be understood ).

Not that this question has anything at all to do with strong or loose
typing, but...if you want features from a loosely typed language, go use a
loosely typed language. C# is decidedly strong-typed. It's a core design
feature of the language.

And if you want reference type semantics, use a reference type.

Pete
 
B

Ben Voigt [C++ MVP]

The problem is that if you have a public field instead of a property,
and you do this:

int? nullableInt = null;

int oops = nullableInt.Value;

No exception is thrown. Instead, "oops" gets the value 0.

Who cares? That's the behavior everyone wants anyway, and gets by using
GetValueOrDefault() which is actually faster than reading Value.

Here's a bigger problem:

int? nInt = null;
nInt = 5;
if (nInt.HasValue) // oops, still false
{...}
 
P

Peter Duniho

Who cares?

Anyone who relies on the current semantics of Nullable said:
That's the behavior everyone wants anyway, and gets by using
GetValueOrDefault() which is actually faster than reading Value.

Lots of code does _not_ use GetValueOrDefault().
Here's a bigger problem:

int? nInt = null;
nInt = 5;
if (nInt.HasValue) // oops, still false
{...}

Sorry, you've lost me. Presumably in this bizarro world where "Value" is
a field instead of a property, the compiler would auto-generate the
assignment to "HasValue" also?

Did you mean to write:

int? nInt = null;
nInt.Value = 5;
if (nInt.HasValue) // oops, still false
{...}

?

That would indeed be the inverse and just-as-serious problem to the one I
mentioned.

Pete
 
B

Ben Voigt [C++ MVP]

Peter said:
Lots of code does _not_ use GetValueOrDefault().

And how much of it is better for not using GetValueOrDefault()?

It's not safe to call Value except after inspecting HasValue, and
HasValue/GetValueOrDefault is faster. Only if you actually want to throw an
InvalidOperationException could Value be useful, but if the value isn't
optional, you shouldn't use Nullable<T> to begin with.

I guess if you wanted to enforce that an initialization function is called
before certain other methods, the Value property could be useful.
Sorry, you've lost me. Presumably in this bizarro world where
"Value" is a field instead of a property, the compiler would
auto-generate the assignment to "HasValue" also?

Did you mean to write:

int? nInt = null;
nInt.Value = 5;
if (nInt.HasValue) // oops, still false
{...}

?

That would indeed be the inverse and just-as-serious problem to the
one I mentioned.

Indeed, that is exactly what I meant.
 
P

Peter Duniho

And how much of it is better for not using GetValueOrDefault()?

It's not "better" or "worse". It's simply different.
It's not safe to call Value except after inspecting HasValue,

Or alternatively said:
and
HasValue/GetValueOrDefault is faster. Only if you actually want to
throw an
InvalidOperationException could Value be useful, but if the value isn't
optional, you shouldn't use Nullable<T> to begin with.

I'm afraid I don't understand what you're saying. I agree that
Nullable<T> is for when the value is optional. But, a missing value does
NOT always mean you are going to substitute the default value for that
missing value. Often, an entirely different code path is taken (for
example, disabling a control that would normally display the value, or
passing DBNull as the value to a database, etc.)
I guess if you wanted to enforce that an initialization function is
called
before certain other methods, the Value property could be useful.

The Value property is useful simply because it more clearly conveys the
usage when the code only ever wants the value, and not a default value in
place of a missing one.

Pete
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
It's not "better" or "worse". It's simply different.




I'm afraid I don't understand what you're saying. I agree that
Nullable<T> is for when the value is optional. But, a missing value does
NOT always mean you are going to substitute the default value for that
missing value. Often, an entirely different code path is taken (for
example, disabling a control that would normally display the value, or
passing DBNull as the value to a database, etc.)

I'm talking about within the branch where HasValue is tested and known to be
true. In this case there is no harm in calling GetValueOrDefault() directly
instead of using the Value property (and the Value getter is too big to
inline I believe, so the extra HasValue check can't be optimized away).

Or would you use the exception to obtain the alternate behavior?
 
P

Peter Duniho

[...]
I'm afraid I don't understand what you're saying. I agree that
Nullable<T> is for when the value is optional. But, a missing value
does NOT always mean you are going to substitute the default value for
that missing value. Often, an entirely different code path is taken
(for example, disabling a control that would normally display the
value, or passing DBNull as the value to a database, etc.)

I'm talking about within the branch where HasValue is tested and known
to be true. In this case there is no harm in calling
GetValueOrDefault() directly instead of using the Value property (and
the Value getter is too big to inline I believe, so the extra HasValue
check can't be optimized away).

Or would you use the exception to obtain the alternate behavior?

No, testing for HasValue or null is better. I would only "rely" on the
exception if that was truly an error and even then it would really only be
for the purpose of saying the user "hey, your dumb programmer forgot to
deal with this case...I'm giving up", or something along those lines. :)

But just because you're testing HasValue and branching (i.e. an if()
statement), that doesn't mean you always want the default value. It just
means you're testing HasValue and branching. It might be that when
there's no value, instead of using the value you just disable a control.
Or maybe you'd pass DBNull to a database. Oh, wait...I already said that.

I really don't understand why you think that the code will _always_ need a
value from the nullable type. I know you're a very experienced
programmer, so presumably you're accustomed to not providing default
values for null reference types, when you have code that allows reference
type variables to be null. The exact same philosophies would apply to
Nullable<T>, and in fact the ability to follow those philosophies is the
primary reason for even using Nullable<T> in the first place. If all
you're ever going to do is use the default value when the Nullable<T> is
null, you might as well just use a plain value type variable and
initialize it to the default value in any situation when you'd otherwise
have set a Nullable<T> to null.

Basically, this scenario makes a lot of sense to me:

DateTime? dt = null;

// some stuff, may leave dt null or may not

if (dt != null)
{
dateTimePicker1.Value = dt.Value;
}
else
{
dateTimePicker1.Enabled = false;
}

On the other hand, why should I prefer this:

int? i = null;

// some stuff, may leave i null or may not

Console.WriteLine("i: " + i.GetValueOrDefault().ToString());

to this:

int i = 0;

// some stuff, may assign something to i or may not

Console.WriteLine("i: " + i.ToString());

And don't say it's because you want to do this:

int? i = null;

// ...
if (i == null)
{
i = 5;
}
// ...

Console.WriteLine("i: " + i.GetValueOrDefault().ToString());

Because that only proves my point (i.e. you're branching based on a null
test and doing something _other_ than retrieving the default or current
value).

The GetValueOrDefault() method certainly has its place. But to say that
one would always (or even most of the time) want to use that rather than
checking HasValue/checking for null seems to entirely miss the scenarios
where Nullable<T> is most useful.

Pete
 
B

Ben Voigt [C++ MVP]

No, testing for HasValue or null is better. I would only "rely" on the
exception if that was truly an error and even then it would really only be
for the purpose of saying the user "hey, your dumb programmer forgot to
deal with this case...I'm giving up", or something along those lines. :)

But just because you're testing HasValue and branching (i.e. an if()
statement), that doesn't mean you always want the default value. It just
means you're testing HasValue and branching. It might be that when
there's no value, instead of using the value you just disable a control.
Or maybe you'd pass DBNull to a database. Oh, wait...I already said that.

I really don't understand why you think that the code will _always_ need a
value from the nullable type. I know you're a very experienced

Inside the branch where HasValue is true, the nullable instance always has a
value so I see no reason not to always use the value stored internally.
programmer, so presumably you're accustomed to not providing default
values for null reference types, when you have code that allows reference
type variables to be null. The exact same philosophies would apply to
Nullable<T>, and in fact the ability to follow those philosophies is the
primary reason for even using Nullable<T> in the first place. If all
you're ever going to do is use the default value when the Nullable<T> is
null, you might as well just use a plain value type variable and
initialize it to the default value in any situation when you'd otherwise
have set a Nullable<T> to null.

Basically, this scenario makes a lot of sense to me:

DateTime? dt = null;

// some stuff, may leave dt null or may not

if (dt != null)
{
dateTimePicker1.Value = dt.Value;
}
else
{
dateTimePicker1.Enabled = false;
}

On the other hand, why should I prefer this:

int? i = null;

// some stuff, may leave i null or may not

Console.WriteLine("i: " + i.GetValueOrDefault().ToString());

to this:

int i = 0;

// some stuff, may assign something to i or may not

Console.WriteLine("i: " + i.ToString());

And don't say it's because you want to do this:

int? i = null;

// ...
if (i == null)
{
i = 5;
}
// ...

Console.WriteLine("i: " + i.GetValueOrDefault().ToString());

Because that only proves my point (i.e. you're branching based on a null
test and doing something _other_ than retrieving the default or current
value).

The GetValueOrDefault() method certainly has its place. But to say that
one would always (or even most of the time) want to use that rather than
checking HasValue/checking for null seems to entirely miss the scenarios
where Nullable<T> is most useful.

I guess I haven't made myself clear.

I'm talking about this (to steal your example):

if (dt.HasValue)
{
dateTimePicker1.Value = dt.GetValueOrDefault();
}
else
{
dateTimePicker1.Enabled = false;
}

After I've checked HasValue, I prefer to just pull the value from the field
directly. GetValueOrDefault accomplishes this, while reading the Value
property does an extra test for null which I know will NEVER be meaningful
(unless the value is being accessed from another thread without
synchronization -- yuck! plus reading the Value property doesn't eliminate
that sort of race anyway)
 
P

Peter Duniho

[...]
I'm talking about this (to steal your example):

if (dt.HasValue)
{
dateTimePicker1.Value = dt.GetValueOrDefault();
}
else
{
dateTimePicker1.Enabled = false;
}

After I've checked HasValue, I prefer to just pull the value from the
field directly. GetValueOrDefault accomplishes this, while reading the
Value property does an extra test for null which I know will NEVER be
meaningful (unless the value is being accessed from another thread
without synchronization -- yuck! plus reading the Value property
doesn't eliminate that sort of race anyway)

Okay, so now I do understand what you mean. I can't say that it seems
like a meaningful optimization to me, and it just clutters up the code in
my view. But that's certainly a subjective matter. In any case, I do
still fail to see how any of this applies to the question that started all
this; namely, whether having a way to protect against reading a Value
field that shouldn't be usable is a useful feature of Nullable<T> or not.

I still maintain that it is. Just because one _can_ use the
GetValueOrDefault() optimization, that doesn't mean that everyone does,
nor does it mean that the class can provide the same semantics as it does
now if the Value member was a public field instead of a property.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top