Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3433994
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T07:38:38+00:00 2026-05-18T07:38:38+00:00

I was wondering why Nullable<T> is a value type, if it is designed to

  • 0

I was wondering why Nullable<T> is a value type, if it is designed to mimic the behavior of reference types? I understand things like GC pressure, but I don’t feel convinced – if we want to have int acting like reference, we are probably OK with all the consequences of having real reference type. I can see no reason why Nullable<T> is not just boxed version of T struct.

As value type:

  1. it still needs to be boxed and unboxed, and more, boxing must be a bit different than with “normal” structs (to treat null-valued nullable like real null)
  2. it needs to be treated differently when checking for null (done simply in Equals, no real problem)
  3. it is mutable, breaking the rule that structs should be immutable (ok, it is logically immutable)
  4. it needs to have special restriction to disallow recursion like Nullable<Nullable<T>>

Doesn’t making Nullable<T> a reference type solve that issues?

rephrased and updated:

I’ve modified my reason list a bit, but my general question is still open:

How will reference type Nullable<T> be worse than current value type implementation? Is it only GC pressure and “small, immutable” rule? It still feels strange for me…

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T07:38:38+00:00Added an answer on May 18, 2026 at 7:38 am

    The reason is that it was not designed to act like a reference type. It was designed to act like a value type, except in just one particular. Let’s look at some ways value types and reference types differ.

    The main difference between a value and reference type, is that value type is self-contained (the variable containing the actual value), while a reference type refers to another value.

    Some other differences are entailed by this. The fact that we can alias reference types directly (which has both good and bad effects) comes from this. So too do differences in what equality means:

    A value type has a concept of equality based on the value contained, which can optionally be redefined (there are logical restrictions on how this redefinition can happen*). A reference type has a concept of identity that is meaningless with value types (as they cannot be directly aliased, so two such values cannot be identical) that can not be redefined, which is also gives the default for its concept of equality. By default, == deals with this value-based equality when it comes to value types†, but with identity when it comes to reference types. Also, even when a reference type is given a value-based concept of equality, and has it used for == it never loses the ability to be compared to another reference for identity.

    Another difference entailed by this is that reference types can be null – a value that refers to another value allows for a value that doesn’t refer to any value, which is what a null reference is.

    Also, some of the advantages of keeping value-types small relate to this, since being based on value, they are copied by value when passed to functions.

    Some other differences are implied but not entailed by this. That it’s often a good idea to make value types immutable is implied but not entailed by the core difference because while there are advantages to be found without considering implementation matters, there are also advantages in doing so with reference types (indeed some relating to safety with aliases apply more immediately to reference types) and reasons why one may break this guideline – so it’s not a hard and fast rule (with nested value types the risks involved are so heavily reduced that I would have few qualms in making a nested value type mutable, even though my style leans heavily to making even reference types immutable when at all practical).

    Some further differences between value types and reference types are arguably implementation details. That a value type in a local variable has the value stored on the stack has been argued as an implementation detail; probably a pretty obvious one if your implementation has a stack, and certainly an important one in some cases, but not core to the definition. It’s also often overstated (for a start, a reference type in a local variable also has the reference itself in the stack, for another there are plenty of times when a value type value is stored in the heap).

    Some further advantages in value types being small relate to this.


    Now, Nullable<T> is a type that behaves like a value type in all the ways described above, except that it can take a null value. Maybe the matter of local values being stored on the stack isn’t all that important (being more an implementation detail than anything else), but the rest is inherent to how it is defined.

    Nullable<T> is defined as

    struct Nullable<T>
    {
        private bool hasValue;
        internal T value;
        /* methods and properties I won't go into here */
    }
    

    Most of the implementation from this point is obvious. Some special handling is needed allow null to be assigned to it – treated as if default(Nullable<T>) had been assigned – and some special handling when boxed, and then the rest follows (including that it can be compared for equality with null).

    If Nullable<T> was a reference type, then we’d have to have special handling to allow for all the rest to occur, along with special handling for features in how .NET helps the developer (such as we’d need special handling to make it descend from ValueType). I’m not even sure if it would be possible.

    *There are some restrictions on how we are allowed to redefine equality. Combining those rules with those used in the defaults, then generally we can allow for two values to be considered equal that would be considered unequal by default, but it rarely makes sense to consider two values unequal that the default would consider equal. A exception is the case where a struct contains only value-types, but where said value-types redefine equality. This the a result of an optimisation, and generally considered a bug rather than by design.

    †An exception is float-point types. Because of the definition of value-types in the CLI standard, double.NaN.Equals(double.NaN) and float.NaN.Equals(float.NaN) return true. But because of the definition of NaN in ISO 60559, float.NaN == float.NaN and double.NaN == double.NaN both return false.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm designing a language, and I'm wondering if it's reasonable to make reference types
Basically, Nullable<T> is a structure, which explains things like calling .HasValue will never throw
Wondering if anyone can help me with this annoying but trivial (in terms of
I was wondering - when would I want to use the .Value member on
I need to select a nullable bit column in a view, but use a
Wondering if anyone can help me understand how the localisation works with keywords. I
I have a type SearchBag that holds a bunch of strings and nullable integers
This seems to work for me, but was wondering if there are any issues
Wondering if anyone has gotten the infamous database is locked error from Trac and
Wondering if there is any Text to Speech software available as a plug in

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.