Struct vs Class

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • JohnGoogle@hotmail.co.uk

    #1

    Struct vs Class

    Hi,

    Newbie question...

    After a recent article in VSJ I had a go at implementing a Fraction
    class to aid my understanding of operator overloading. After a previous
    message someone suggested that I implement it as a struct rather than a
    class which I did and all worked OK.

    The simplest declaration for the struct is:

    public struct Fraction
    {
    private Int32 _numerator;
    private Int32 _denominator;

    public Int32 numerator
    {
    get { return _numerator; }
    }

    public Int32 denominator
    {
    get { return _denominator; }
    }

    public Fraction(Int32 numerator)
    {
    this._numerator = numerator;
    this._denominat or = 1;
    }

    public Fraction(Int32 numerator, Int32 denominator)
    {
    this._numerator = numerator;
    this._denominat or = denominator;
    if (denominator < 1)
    throw new ArgumentExcepti on("Fraction denominator value
    '" + denominator.ToS tring() + "' is invalid.");
    }

    // All other declarations follow (for overloads of
    +,-,*,/,++,--,>,<, etc).
    }


    As you can see, it is essential that the denominator must be 1 or more.
    As it was originally a class, the constructors ensured that the
    denominator was >= 1. Alos, the numerator and denominator values are
    read only as they can only be modified by operators such as +,-,++,*,/
    etc (not shown).

    However, during my testing I realised that, as a struct, it is possible
    to declare a struct which is initialised to 0 so the denominator
    becomes illegal.

    I've found that you cannot declare a parameterless construction such
    as:

    public struct Fraction
    {
    private Int32 _numerator;
    private Int32 _denominator;
    ....
    public Fraction()
    {
    this._numerator = 0;
    this._denominat or = 1;
    }
    ....
    }

    This gives a compiler error: 'Structs cannot contain explicit
    parameterless constructors'.


    Also, you cannot initialise the fields of a struct such as:

    public struct Fraction
    {
    private Int32 _numerator;
    private Int32 _denominator = 1;
    ....
    }

    This gives a compilation error: '_denominator': cannot have instance
    field initializers in structs'.


    Is there any way to force a field of a struct to be initialised to a
    non zero value?

    If not, I'll go back to implementing it as a class.

    TIA,

    John.

  • Dave Sexton

    #2
    Re: Struct vs Class

    Hi,

    You can't prevent the initialization of an instance of a struct with default
    values. You'll always be able to code: Fraction fr = new Fraction(),
    regardless of the constructors that you define.

    If you decide to stick with a struct, don't forget to override Equals and
    GetHashCode as well. And make sure that their return values are deterministic
    and consistent with each other.

    --
    Dave Sexton

    <JohnGoogle@hot mail.co.ukwrote in message
    news:1162071782 .355396.265210@ k70g2000cwa.goo glegroups.com.. .
    Hi,
    >
    Newbie question...
    >
    After a recent article in VSJ I had a go at implementing a Fraction
    class to aid my understanding of operator overloading. After a previous
    message someone suggested that I implement it as a struct rather than a
    class which I did and all worked OK.
    >
    The simplest declaration for the struct is:
    >
    public struct Fraction
    {
    private Int32 _numerator;
    private Int32 _denominator;
    >
    public Int32 numerator
    {
    get { return _numerator; }
    }
    >
    public Int32 denominator
    {
    get { return _denominator; }
    }
    >
    public Fraction(Int32 numerator)
    {
    this._numerator = numerator;
    this._denominat or = 1;
    }
    >
    public Fraction(Int32 numerator, Int32 denominator)
    {
    this._numerator = numerator;
    this._denominat or = denominator;
    if (denominator < 1)
    throw new ArgumentExcepti on("Fraction denominator value
    '" + denominator.ToS tring() + "' is invalid.");
    }
    >
    // All other declarations follow (for overloads of
    +,-,*,/,++,--,>,<, etc).
    }
    >
    >
    As you can see, it is essential that the denominator must be 1 or more.
    As it was originally a class, the constructors ensured that the
    denominator was >= 1. Alos, the numerator and denominator values are
    read only as they can only be modified by operators such as +,-,++,*,/
    etc (not shown).
    >
    However, during my testing I realised that, as a struct, it is possible
    to declare a struct which is initialised to 0 so the denominator
    becomes illegal.
    >
    I've found that you cannot declare a parameterless construction such
    as:
    >
    public struct Fraction
    {
    private Int32 _numerator;
    private Int32 _denominator;
    ....
    public Fraction()
    {
    this._numerator = 0;
    this._denominat or = 1;
    }
    ....
    }
    >
    This gives a compiler error: 'Structs cannot contain explicit
    parameterless constructors'.
    >
    >
    Also, you cannot initialise the fields of a struct such as:
    >
    public struct Fraction
    {
    private Int32 _numerator;
    private Int32 _denominator = 1;
    ....
    }
    >
    This gives a compilation error: '_denominator': cannot have instance
    field initializers in structs'.
    >
    >
    Is there any way to force a field of a struct to be initialised to a
    non zero value?
    >
    If not, I'll go back to implementing it as a class.
    >
    TIA,
    >
    John.
    >

    Comment

    • JohnGoogle@hotmail.co.uk

      #3
      Re: Struct vs Class

      Thanks Dave,

      I do override Equals and GetHashcode already. I guess I'll change it
      back to a class. Thank you for you feedback. From what I had read, I
      thought this was the case.

      As a newbie, I'm interested in how much boxing / unboxing will be going
      on when I define a struct as opposed to a class. I've just got Jeffrey
      Richter's CLR via C# which seems to show me how to determine this via
      the IL Disassembler. Some investigations to be done!

      Thanks.

      John.

      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: Struct vs Class

        <JohnGoogle@hot mail.co.ukwrote :

        <snip>
        Is there any way to force a field of a struct to be initialised to a
        non zero value?
        No - and you'll always end up with the zero value if you create, say,
        an array of the struct type.
        If not, I'll go back to implementing it as a class.
        I wouldn't make that the most important influence in your decision.
        It's easy to ensure that the struct is initialised appropriately
        wherever it's actually used. Think of a zero value for a struct as a
        sort of equivalent (in this particular case) to a null value for a
        reference type. Just as you could do:

        FractionStruct x = new FractionStruct( ); // x is useless at the moment

        you could do:

        FractionClass y = null; // y is just as useless at the moment


        A fraction still feels more like a value type than a reference type to
        me.

        --
        Jon Skeet - <skeet@pobox.co m>
        http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
        If replying to the group, please do not mail me too

        Comment

        • Bruce Wood

          #5
          Re: Struct vs Class


          JohnGoogle@hotm ail.co.uk wrote:
          Thanks Dave,
          >
          I do override Equals and GetHashcode already. I guess I'll change it
          back to a class. Thank you for you feedback. From what I had read, I
          thought this was the case.
          >
          As a newbie, I'm interested in how much boxing / unboxing will be going
          on when I define a struct as opposed to a class. I've just got Jeffrey
          Richter's CLR via C# which seems to show me how to determine this via
          the IL Disassembler. Some investigations to be done!
          I, too, created a Fraction class for use in our company. Trust me:
          don't make it a class. Simply assign meaning to "everything zero". It's
          "essential" that the denominator be greater than zero only if you say
          it's essential; you're writing the code, so you can make any
          assumptions you want.

          Simply write the internals so that denominator and numerator both zero
          means "zero". Yes, it means more checks inside your code, but as I
          said, trust me: making this a class will make it much less useful and
          make it act much less intuitively. It should be a struct.

          Comment

          • Ryan

            #6
            Re: Struct vs Class

            You could make the _denominator field nullable and check for null in
            the property:

            public struct Fraction {
            private Int32? _denominator;

            [...]
            public Int32 Denominator {
            get{ if ( _denominator == null ) return 1; else return
            (Int32)_denomin ator; }
            }

            [...]
            }

            Regards
            ,
            Ryan

            On Oct 28, 4:43 pm, JohnGoo...@hotm ail.co.uk wrote:
            Hi,
            >
            Newbie question...
            >
            After a recent article in VSJ I had a go at implementing a Fraction
            class to aid my understanding of operator overloading. After a previous
            message someone suggested that I implement it as a struct rather than a
            class which I did and all worked OK.
            >
            The simplest declaration for the struct is:
            >
            public struct Fraction
            {
            private Int32 _numerator;
            private Int32 _denominator;
            >
            public Int32 numerator
            {
            get { return _numerator; }
            }
            >
            public Int32 denominator
            {
            get { return _denominator; }
            }
            >
            public Fraction(Int32 numerator)
            {
            this._numerator = numerator;
            this._denominat or = 1;
            }
            >
            public Fraction(Int32 numerator, Int32 denominator)
            {
            this._numerator = numerator;
            this._denominat or = denominator;
            if (denominator < 1)
            throw new ArgumentExcepti on("Fraction denominator value
            '" + denominator.ToS tring() + "' is invalid.");
            }
            >
            // All other declarations follow (for overloads of
            +,-,*,/,++,--,>,<, etc).
            }
            >
            As you can see, it is essential that the denominator must be 1 or more.
            As it was originally a class, the constructors ensured that the
            denominator was >= 1. Alos, the numerator and denominator values are
            read only as they can only be modified by operators such as +,-,++,*,/
            etc (not shown).
            >
            However, during my testing I realised that, as a struct, it is possible
            to declare a struct which is initialised to 0 so the denominator
            becomes illegal.
            >
            I've found that you cannot declare a parameterless construction such
            as:
            >
            public struct Fraction
            {
            private Int32 _numerator;
            private Int32 _denominator;
            ....
            public Fraction()
            {
            this._numerator = 0;
            this._denominat or = 1;
            }
            ....
            }
            >
            This gives a compiler error: 'Structs cannot contain explicit
            parameterless constructors'.
            >
            Also, you cannot initialise the fields of a struct such as:
            >
            public struct Fraction
            {
            private Int32 _numerator;
            private Int32 _denominator = 1;
            ....
            }
            >
            This gives a compilation error: '_denominator': cannot have instance
            field initializers in structs'.
            >
            Is there any way to force a field of a struct to be initialised to a
            non zero value?
            >
            If not, I'll go back to implementing it as a class.
            >
            TIA,
            >
            John.

            Comment

            • Martin Z

              #7
              Re: Struct vs Class

              In general you want a way to flag the object as "uninitiali zed" - while
              there are numerous clever ways to do it, ultimately the simplest
              approach is to include a boolean. It's tempting to use a nullable
              type, but afaik nullables are reference types, thus eliminating the
              niceties using a struct. Structs work so much better when only
              containing values.

              As such, include a private boolean "isDenominatorI initialized" - and
              use

              public Int32 Denominator {
              get{ if (isDenominatorI initialized == false ) return 1; else
              return (Int32)_denomin ator; }
              private set {isDenominatorI nitialized = true; _denominator =
              value; }
              }

              And then use the private set whenever you (internally) assign to the
              denominator. This assumes 2.0 where you can have differing access to
              get/set attributes. This should perform better than the nullable
              approach.

              Ryan wrote:
              You could make the _denominator field nullable and check for null in
              the property:
              >
              public struct Fraction {
              private Int32? _denominator;
              >
              [...]
              public Int32 Denominator {
              get{ if ( _denominator == null ) return 1; else return
              (Int32)_denomin ator; }
              }
              >
              [...]
              }
              >
              Regards
              ,
              Ryan
              >
              On Oct 28, 4:43 pm, JohnGoo...@hotm ail.co.uk wrote:
              Hi,

              Newbie question...

              After a recent article in VSJ I had a go at implementing a Fraction
              class to aid my understanding of operator overloading. After a previous
              message someone suggested that I implement it as a struct rather than a
              class which I did and all worked OK.

              The simplest declaration for the struct is:

              public struct Fraction
              {
              private Int32 _numerator;
              private Int32 _denominator;

              public Int32 numerator
              {
              get { return _numerator; }
              }

              public Int32 denominator
              {
              get { return _denominator; }
              }

              public Fraction(Int32 numerator)
              {
              this._numerator = numerator;
              this._denominat or = 1;
              }

              public Fraction(Int32 numerator, Int32 denominator)
              {
              this._numerator = numerator;
              this._denominat or = denominator;
              if (denominator < 1)
              throw new ArgumentExcepti on("Fraction denominator value
              '" + denominator.ToS tring() + "' is invalid.");
              }

              // All other declarations follow (for overloads of
              +,-,*,/,++,--,>,<, etc).
              }

              As you can see, it is essential that the denominator must be 1 or more.
              As it was originally a class, the constructors ensured that the
              denominator was >= 1. Alos, the numerator and denominator values are
              read only as they can only be modified by operators such as +,-,++,*,/
              etc (not shown).

              However, during my testing I realised that, as a struct, it is possible
              to declare a struct which is initialised to 0 so the denominator
              becomes illegal.

              I've found that you cannot declare a parameterless construction such
              as:

              public struct Fraction
              {
              private Int32 _numerator;
              private Int32 _denominator;
              ....
              public Fraction()
              {
              this._numerator = 0;
              this._denominat or = 1;
              }
              ....
              }

              This gives a compiler error: 'Structs cannot contain explicit
              parameterless constructors'.

              Also, you cannot initialise the fields of a struct such as:

              public struct Fraction
              {
              private Int32 _numerator;
              private Int32 _denominator = 1;
              ....
              }

              This gives a compilation error: '_denominator': cannot have instance
              field initializers in structs'.

              Is there any way to force a field of a struct to be initialised to a
              non zero value?

              If not, I'll go back to implementing it as a class.

              TIA,

              John.

              Comment

              • Martin Z

                #8
                Re: Struct vs Class

                Bruce, My understanding is that, if designed to be entirely immutable
                and containing no events, then there is almost no visible difference
                between a class and a struct. The struct is primarily a
                speed-optimization - access to stack-variables is much faster. Hence,
                structs should only contain other valuetypes.

                Bruce Wood wrote:
                JohnGoogle@hotm ail.co.uk wrote:
                Thanks Dave,

                I do override Equals and GetHashcode already. I guess I'll change it
                back to a class. Thank you for you feedback. From what I had read, I
                thought this was the case.

                As a newbie, I'm interested in how much boxing / unboxing will be going
                on when I define a struct as opposed to a class. I've just got Jeffrey
                Richter's CLR via C# which seems to show me how to determine this via
                the IL Disassembler. Some investigations to be done!
                >
                I, too, created a Fraction class for use in our company. Trust me:
                don't make it a class. Simply assign meaning to "everything zero". It's
                "essential" that the denominator be greater than zero only if you say
                it's essential; you're writing the code, so you can make any
                assumptions you want.
                >
                Simply write the internals so that denominator and numerator both zero
                means "zero". Yes, it means more checks inside your code, but as I
                said, trust me: making this a class will make it much less useful and
                make it act much less intuitively. It should be a struct.

                Comment

                • Dave Sexton

                  #9
                  Re: Struct vs Class

                  Hi Martin,
                  The struct is primarily a
                  speed-optimization - access to stack-variables is much faster. Hence,
                  structs should only contain other valuetypes.
                  But values can be stored on the heap as well.

                  Check out this article by Jon Skeet:


                  Structs that have private fields that reference objects simply store the
                  reference with the rest of the structure. Memory-wise, it's just like storing
                  Int32, AFAIK.

                  A value type is meant to be just that - a value. Values are not meant to be
                  tangible objects - like paper - they are meant to represent a value that you
                  can assign to an object - like worth (money). Therefore, it makes sense to me
                  that values are stored in-line with the objects that contain them, or on the
                  stack if that's where they are placed. They stay with their container because
                  they only have value, not presence.

                  I ask myself the following question when choosing between a struct or class
                  definition:

                  When an instance is used as a hash key, should the corresponding value in a
                  hash table be accessible by value or by reference only?

                  In other words, will I need the reference of the entity in order to retrieve
                  the keyed value at a later time, or just the value?

                  It's usually obvious whether to use a struct or a class from there, even if I
                  don't plan on using any instances to key a hash table. I never take into
                  consideration whether the struct will contain references, however I don't
                  think I've ever created a struct that had references anyway - so I might agree
                  with you after all, but for a different reason :)

                  --
                  Dave Sexton

                  "Martin Z" <martin.zarate@ gmail.comwrote in message
                  news:1162223702 .670212.7060@k7 0g2000cwa.googl egroups.com...
                  Bruce, My understanding is that, if designed to be entirely immutable
                  and containing no events, then there is almost no visible difference
                  between a class and a struct. The struct is primarily a
                  speed-optimization - access to stack-variables is much faster. Hence,
                  structs should only contain other valuetypes.
                  >
                  Bruce Wood wrote:
                  >JohnGoogle@hotm ail.co.uk wrote:
                  Thanks Dave,
                  >
                  I do override Equals and GetHashcode already. I guess I'll change it
                  back to a class. Thank you for you feedback. From what I had read, I
                  thought this was the case.
                  >
                  As a newbie, I'm interested in how much boxing / unboxing will be going
                  on when I define a struct as opposed to a class. I've just got Jeffrey
                  Richter's CLR via C# which seems to show me how to determine this via
                  the IL Disassembler. Some investigations to be done!
                  >>
                  >I, too, created a Fraction class for use in our company. Trust me:
                  >don't make it a class. Simply assign meaning to "everything zero". It's
                  >"essential" that the denominator be greater than zero only if you say
                  >it's essential; you're writing the code, so you can make any
                  >assumptions you want.
                  >>
                  >Simply write the internals so that denominator and numerator both zero
                  >means "zero". Yes, it means more checks inside your code, but as I
                  >said, trust me: making this a class will make it much less useful and
                  >make it act much less intuitively. It should be a struct.
                  >

                  Comment

                  • Bruce Wood

                    #10
                    Re: Struct vs Class


                    Martin Z wrote:
                    Bruce, My understanding is that, if designed to be entirely immutable
                    and containing no events, then there is almost no visible difference
                    between a class and a struct.
                    Apparently so. I'm trying to think of differences in behaviour between
                    an immutable class and a struct, and I can't. Of course, it's Monday
                    morning. I could be wrong.

                    One would have to overload == appropriately (and, one presumes, the
                    other mathematical and comparison operators), but apart from that I
                    can't think of any hitches. Of course, the temptation with a class
                    would be to make it mutable, but that's just a temptation, not a given.
                    The struct is primarily a speed-optimization - access to stack-variables is much faster.
                    I wouldn't state that as the primary speed benefits of structs. I
                    consider the primary speed benefit of structs being that they don't
                    need to be garbage-collected. So, if you are doing extensive
                    calculations that involve the creation of myriad intermediate results
                    then structs are a better choice because objects created on the heap
                    have to be GC'd.

                    However, this is only one consideration in whether to make something a
                    struct or a class, and not even the most important. The most important
                    consideration, IMHO, is whether the thing you want to create displays
                    _value semantics_. There are lots of discussions in this newsgroup
                    about struct vs class and value vs reference semantics.
                    Hence, structs should only contain other valuetypes.
                    No, I disagree. For example, I have a struct called a Measure, which
                    contains a decimal quantity and a unit of measure. UnitOfMeasure is a(n
                    immutable) reference type. I think that our disagreement on this point
                    goes back to the speed benefits of structs: I see storage on the stack
                    as a side-effect of using structs, not as a motivation for using
                    structs, and so I don't see anything wrong with structs that contain
                    references. Of course, structs that contain references to _mutable_
                    objects can lead to some awfully puzzling, nearly-unpredictable
                    behaviour, so I wouldn't recommend that. :-)

                    Comment

                    • Bruce Wood

                      #11
                      Re: Struct vs Class


                      Martin Z wrote:
                      afaik nullables are reference types
                      Nope. From the MSDN doc:

                      http://msdn2.microsoft.com/en-us/library/1t3y8s4s.aspx

                      "Nullable types are instances of the System.Nullable struct."

                      Nullable types are value types, not reference types. They contain a
                      boolean flag indicating whether they are null or not, and space for the
                      value if they are not null.

                      Comment

                      • Dave Sexton

                        #12
                        Re: Struct vs Class

                        Hi Bruce,
                        Of course, structs that contain references to _mutable_
                        objects can lead to some awfully puzzling, nearly-unpredictable
                        behaviour, so I wouldn't recommend that. :-)
                        DictionaryEntry is one that doesn't conform to that idea, however.

                        --
                        Dave Sexton

                        "Bruce Wood" <brucewood@cana da.comwrote in message
                        news:1162229711 .383330.47510@b 28g2000cwb.goog legroups.com...
                        >
                        Martin Z wrote:
                        >Bruce, My understanding is that, if designed to be entirely immutable
                        >and containing no events, then there is almost no visible difference
                        >between a class and a struct.
                        >
                        Apparently so. I'm trying to think of differences in behaviour between
                        an immutable class and a struct, and I can't. Of course, it's Monday
                        morning. I could be wrong.
                        >
                        One would have to overload == appropriately (and, one presumes, the
                        other mathematical and comparison operators), but apart from that I
                        can't think of any hitches. Of course, the temptation with a class
                        would be to make it mutable, but that's just a temptation, not a given.
                        >
                        >The struct is primarily a speed-optimization - access to stack-variables is
                        >much faster.
                        >
                        I wouldn't state that as the primary speed benefits of structs. I
                        consider the primary speed benefit of structs being that they don't
                        need to be garbage-collected. So, if you are doing extensive
                        calculations that involve the creation of myriad intermediate results
                        then structs are a better choice because objects created on the heap
                        have to be GC'd.
                        >
                        However, this is only one consideration in whether to make something a
                        struct or a class, and not even the most important. The most important
                        consideration, IMHO, is whether the thing you want to create displays
                        _value semantics_. There are lots of discussions in this newsgroup
                        about struct vs class and value vs reference semantics.
                        >
                        >Hence, structs should only contain other valuetypes.
                        >
                        No, I disagree. For example, I have a struct called a Measure, which
                        contains a decimal quantity and a unit of measure. UnitOfMeasure is a(n
                        immutable) reference type. I think that our disagreement on this point
                        goes back to the speed benefits of structs: I see storage on the stack
                        as a side-effect of using structs, not as a motivation for using
                        structs, and so I don't see anything wrong with structs that contain
                        references. Of course, structs that contain references to _mutable_
                        objects can lead to some awfully puzzling, nearly-unpredictable
                        behaviour, so I wouldn't recommend that. :-)
                        >

                        Comment

                        • Martin Z

                          #13
                          Re: Struct vs Class

                          Holy poop, DictionaryEntry is mutable? (off to MSDN).... Whoa. Oh,
                          and my comment about avoiding including value-types in structs was from
                          the optimization direction - obviously if you're using structs because
                          you want value-type semantics then it doesn't matter what you stuff in
                          them (as long as they're immutable to avoid confusing aliasing
                          behaviour).

                          Funny that nullables are value-type - I recently got an error from the
                          XmlSerializer where it complained that they were reference types, and
                          thus couldn't be XmlAttributes. That was just silly.

                          Anyhow, I think the reason DictionaryEntry is mutable is just because
                          people got really sick of saying new DictionaryEntry <MyKeyType,
                          MyValueType- not for any good technical reason. I think it's
                          hilarious that the structs have the nice immediate-setting semantics
                          for mutable structs
                          myStructClass foo;
                          foo.bar = 1;
                          foo.baz = 2;
                          //all parameters initialized, it's ready to use, no constructor
                          needed.

                          but you can only use them with mutable structs anyways, making it
                          completely useless since MS says to never-ever-do-mutable-structs. I
                          want the readonly attribute to apply to property setters, and then
                          integrate that with the 3.0 Object Initializers so we can have some
                          non-excruciating syntax for immutables.

                          Dave Sexton wrote:
                          Hi Bruce,
                          >
                          Of course, structs that contain references to _mutable_
                          objects can lead to some awfully puzzling, nearly-unpredictable
                          behaviour, so I wouldn't recommend that. :-)
                          >
                          DictionaryEntry is one that doesn't conform to that idea, however.
                          >
                          --
                          Dave Sexton
                          >
                          "Bruce Wood" <brucewood@cana da.comwrote in message
                          news:1162229711 .383330.47510@b 28g2000cwb.goog legroups.com...

                          Martin Z wrote:
                          Bruce, My understanding is that, if designed to be entirely immutable
                          and containing no events, then there is almost no visible difference
                          between a class and a struct.
                          Apparently so. I'm trying to think of differences in behaviour between
                          an immutable class and a struct, and I can't. Of course, it's Monday
                          morning. I could be wrong.

                          One would have to overload == appropriately (and, one presumes, the
                          other mathematical and comparison operators), but apart from that I
                          can't think of any hitches. Of course, the temptation with a class
                          would be to make it mutable, but that's just a temptation, not a given.
                          The struct is primarily a speed-optimization - access to stack-variables is
                          much faster.
                          I wouldn't state that as the primary speed benefits of structs. I
                          consider the primary speed benefit of structs being that they don't
                          need to be garbage-collected. So, if you are doing extensive
                          calculations that involve the creation of myriad intermediate results
                          then structs are a better choice because objects created on the heap
                          have to be GC'd.

                          However, this is only one consideration in whether to make something a
                          struct or a class, and not even the most important. The most important
                          consideration, IMHO, is whether the thing you want to create displays
                          _value semantics_. There are lots of discussions in this newsgroup
                          about struct vs class and value vs reference semantics.
                          Hence, structs should only contain other valuetypes.
                          No, I disagree. For example, I have a struct called a Measure, which
                          contains a decimal quantity and a unit of measure. UnitOfMeasure is a(n
                          immutable) reference type. I think that our disagreement on this point
                          goes back to the speed benefits of structs: I see storage on the stack
                          as a side-effect of using structs, not as a motivation for using
                          structs, and so I don't see anything wrong with structs that contain
                          references. Of course, structs that contain references to _mutable_
                          objects can lead to some awfully puzzling, nearly-unpredictable
                          behaviour, so I wouldn't recommend that. :-)

                          Comment

                          • Dave Sexton

                            #14
                            Re: Struct vs Class

                            Hi Martin,
                            obviously if you're using structs because
                            you want value-type semantics then it doesn't matter what you stuff in
                            them (as long as they're immutable to avoid confusing aliasing
                            behaviour).
                            What do you mean by "aliasing behaviour"?
                            Funny that nullables are value-type - I recently got an error from the
                            XmlSerializer where it complained that they were reference types, and
                            thus couldn't be XmlAttributes. That was just silly.
                            I think Nullable<Tshoul d be a value type just like DictionaryEntry . They
                            each assign a value to the objects that they contain - nullability or hash
                            entry, respectively.

                            Although nullability is only useful for value types, which is why I suspect
                            that you can't make a Nullable<string >, for example.

                            But hash entries can be anything, including mutable objects. DictionaryEntry
                            is just a value: the relationship between a key and its corresponding value.
                            If the key or the value are object references then the value of the hash entry
                            itself is simply the relationship between the two references. If another
                            DictionaryEntry contains the same key and value references, then the values of
                            the DictionaryEntri es are equal.

                            Nullable<Tand DictionaryEntry do not represent tangible objects, they
                            represent assignable values. It helps some people to think of values as
                            conceptual and objects as physical, like me!
                            Anyhow, I think the reason DictionaryEntry is mutable is just because
                            people got really sick of saying new DictionaryEntry <MyKeyType,
                            MyValueType- not for any good technical reason.
                            I've never actually created an instance of DictionaryEntry though. I've only
                            used it in iterators so I'm not sure the mutability was necessary. I assume
                            the author(s) made it mutable due to some internal implementation constraints
                            that I don't feel like searching for right now :)

                            But just to clear things up, my response to Bruce wasn't about the mutability
                            of DictionaryEntry , it was about the mutability of the objects that it
                            references. That's what I assumed Bruce meant when he wrote, "structs that
                            contain references to _mutable_ objects", although reading it out-of-context
                            now I can see why you thought that.
                            I think it's
                            hilarious that the structs have the nice immediate-setting semantics
                            for mutable structs
                            myStructClass foo;
                            foo.bar = 1;
                            foo.baz = 2;
                            //all parameters initialized, it's ready to use, no constructor
                            needed.
                            but you can only use them with mutable structs anyways, making it
                            completely useless since MS says to never-ever-do-mutable-structs. I
                            want the readonly attribute to apply to property setters, and then
                            integrate that with the 3.0 Object Initializers so we can have some
                            non-excruciating syntax for immutables.
                            I won't argue that :)

                            --
                            Dave Sexton

                            "Martin Z" <martin.zarate@ gmail.comwrote in message
                            news:1162232606 .318831.243760@ b28g2000cwb.goo glegroups.com.. .
                            Holy poop, DictionaryEntry is mutable? (off to MSDN).... Whoa. Oh,
                            and my comment about avoiding including value-types in structs was from
                            the optimization direction - obviously if you're using structs because
                            you want value-type semantics then it doesn't matter what you stuff in
                            them (as long as they're immutable to avoid confusing aliasing
                            behaviour).
                            >
                            Funny that nullables are value-type - I recently got an error from the
                            XmlSerializer where it complained that they were reference types, and
                            thus couldn't be XmlAttributes. That was just silly.
                            >
                            Anyhow, I think the reason DictionaryEntry is mutable is just because
                            people got really sick of saying new DictionaryEntry <MyKeyType,
                            MyValueType- not for any good technical reason. I think it's
                            hilarious that the structs have the nice immediate-setting semantics
                            for mutable structs
                            myStructClass foo;
                            foo.bar = 1;
                            foo.baz = 2;
                            //all parameters initialized, it's ready to use, no constructor
                            needed.
                            >
                            but you can only use them with mutable structs anyways, making it
                            completely useless since MS says to never-ever-do-mutable-structs. I
                            want the readonly attribute to apply to property setters, and then
                            integrate that with the 3.0 Object Initializers so we can have some
                            non-excruciating syntax for immutables.
                            >
                            Dave Sexton wrote:
                            >Hi Bruce,
                            >>
                            Of course, structs that contain references to _mutable_
                            objects can lead to some awfully puzzling, nearly-unpredictable
                            behaviour, so I wouldn't recommend that. :-)
                            >>
                            >DictionaryEntr y is one that doesn't conform to that idea, however.
                            >>
                            >--
                            >Dave Sexton
                            >>
                            >"Bruce Wood" <brucewood@cana da.comwrote in message
                            >news:116222971 1.383330.47510@ b28g2000cwb.goo glegroups.com.. .
                            >
                            Martin Z wrote:
                            >Bruce, My understanding is that, if designed to be entirely immutable
                            >and containing no events, then there is almost no visible difference
                            >between a class and a struct.
                            >
                            Apparently so. I'm trying to think of differences in behaviour between
                            an immutable class and a struct, and I can't. Of course, it's Monday
                            morning. I could be wrong.
                            >
                            One would have to overload == appropriately (and, one presumes, the
                            other mathematical and comparison operators), but apart from that I
                            can't think of any hitches. Of course, the temptation with a class
                            would be to make it mutable, but that's just a temptation, not a given.
                            >
                            >The struct is primarily a speed-optimization - access to stack-variables
                            >is
                            >much faster.
                            >
                            I wouldn't state that as the primary speed benefits of structs. I
                            consider the primary speed benefit of structs being that they don't
                            need to be garbage-collected. So, if you are doing extensive
                            calculations that involve the creation of myriad intermediate results
                            then structs are a better choice because objects created on the heap
                            have to be GC'd.
                            >
                            However, this is only one consideration in whether to make something a
                            struct or a class, and not even the most important. The most important
                            consideration, IMHO, is whether the thing you want to create displays
                            _value semantics_. There are lots of discussions in this newsgroup
                            about struct vs class and value vs reference semantics.
                            >
                            >Hence, structs should only contain other valuetypes.
                            >
                            No, I disagree. For example, I have a struct called a Measure, which
                            contains a decimal quantity and a unit of measure. UnitOfMeasure is a(n
                            immutable) reference type. I think that our disagreement on this point
                            goes back to the speed benefits of structs: I see storage on the stack
                            as a side-effect of using structs, not as a motivation for using
                            structs, and so I don't see anything wrong with structs that contain
                            references. Of course, structs that contain references to _mutable_
                            objects can lead to some awfully puzzling, nearly-unpredictable
                            behaviour, so I wouldn't recommend that. :-)
                            >
                            >

                            Comment

                            • Martin Z

                              #15
                              Re: Struct vs Class

                              structs containing references to mutable objects is what I meant by
                              "aliasing" - that is, if I have a struct I may assume that everything I
                              do with it will be copy-semantics... however, if it contains a
                              reference to a mutable class (say a stringbuilder) then if I make
                              changes to that stringbuilder, then all copies (not just the object I'm
                              accessing to make the changes) will see that, which is unexpected
                              behaviour for a struct. That is, an alias where we expect a copy.

                              And yes, I agree that Nullables _should_ be valuetype, and likely are
                              in implementation - I just thought that they were reference-types
                              because errors thrown by the XmlSerializer informed me that they were
                              reference types... which is likely just the serializer getting very
                              confused by the concept of a nullable value-type.

                              Dave Sexton wrote:
                              Hi Martin,
                              >
                              obviously if you're using structs because
                              you want value-type semantics then it doesn't matter what you stuff in
                              them (as long as they're immutable to avoid confusing aliasing
                              behaviour).
                              >
                              What do you mean by "aliasing behaviour"?
                              >
                              Funny that nullables are value-type - I recently got an error from the
                              XmlSerializer where it complained that they were reference types, and
                              thus couldn't be XmlAttributes. That was just silly.
                              >
                              I think Nullable<Tshoul d be a value type just like DictionaryEntry . They
                              each assign a value to the objects that they contain - nullability or hash
                              entry, respectively.
                              >
                              Although nullability is only useful for value types, which is why I suspect
                              that you can't make a Nullable<string >, for example.
                              >
                              But hash entries can be anything, including mutable objects. DictionaryEntry
                              is just a value: the relationship between a key and its corresponding value.
                              If the key or the value are object references then the value of the hash entry
                              itself is simply the relationship between the two references. If another
                              DictionaryEntry contains the same key and value references, then the values of
                              the DictionaryEntri es are equal.
                              >
                              Nullable<Tand DictionaryEntry do not represent tangible objects, they
                              represent assignable values. It helps some people to think of values as
                              conceptual and objects as physical, like me!
                              >
                              Anyhow, I think the reason DictionaryEntry is mutable is just because
                              people got really sick of saying new DictionaryEntry <MyKeyType,
                              MyValueType- not for any good technical reason.
                              >
                              I've never actually created an instance of DictionaryEntry though. I've only
                              used it in iterators so I'm not sure the mutability was necessary. I assume
                              the author(s) made it mutable due to some internal implementation constraints
                              that I don't feel like searching for right now :)
                              >
                              But just to clear things up, my response to Bruce wasn't about the mutability
                              of DictionaryEntry , it was about the mutability of the objects that it
                              references. That's what I assumed Bruce meant when he wrote, "structs that
                              contain references to _mutable_ objects", although reading it out-of-context
                              now I can see why you thought that.
                              >
                              I think it's
                              hilarious that the structs have the nice immediate-setting semantics
                              for mutable structs
                              myStructClass foo;
                              foo.bar = 1;
                              foo.baz = 2;
                              //all parameters initialized, it's ready to use, no constructor
                              needed.
                              >
                              but you can only use them with mutable structs anyways, making it
                              completely useless since MS says to never-ever-do-mutable-structs. I
                              want the readonly attribute to apply to property setters, and then
                              integrate that with the 3.0 Object Initializers so we can have some
                              non-excruciating syntax for immutables.
                              >
                              I won't argue that :)
                              >
                              --
                              Dave Sexton
                              >
                              "Martin Z" <martin.zarate@ gmail.comwrote in message
                              news:1162232606 .318831.243760@ b28g2000cwb.goo glegroups.com.. .
                              Holy poop, DictionaryEntry is mutable? (off to MSDN).... Whoa. Oh,
                              and my comment about avoiding including value-types in structs was from
                              the optimization direction - obviously if you're using structs because
                              you want value-type semantics then it doesn't matter what you stuff in
                              them (as long as they're immutable to avoid confusing aliasing
                              behaviour).

                              Funny that nullables are value-type - I recently got an error from the
                              XmlSerializer where it complained that they were reference types, and
                              thus couldn't be XmlAttributes. That was just silly.

                              Anyhow, I think the reason DictionaryEntry is mutable is just because
                              people got really sick of saying new DictionaryEntry <MyKeyType,
                              MyValueType- not for any good technical reason. I think it's
                              hilarious that the structs have the nice immediate-setting semantics
                              for mutable structs
                              myStructClass foo;
                              foo.bar = 1;
                              foo.baz = 2;
                              //all parameters initialized, it's ready to use, no constructor
                              needed.

                              but you can only use them with mutable structs anyways, making it
                              completely useless since MS says to never-ever-do-mutable-structs. I
                              want the readonly attribute to apply to property setters, and then
                              integrate that with the 3.0 Object Initializers so we can have some
                              non-excruciating syntax for immutables.

                              Dave Sexton wrote:
                              Hi Bruce,
                              >
                              Of course, structs that contain references to _mutable_
                              objects can lead to some awfully puzzling, nearly-unpredictable
                              behaviour, so I wouldn't recommend that. :-)
                              >
                              DictionaryEntry is one that doesn't conform to that idea, however.
                              >
                              --
                              Dave Sexton
                              >
                              "Bruce Wood" <brucewood@cana da.comwrote in message
                              news:1162229711 .383330.47510@b 28g2000cwb.goog legroups.com...

                              Martin Z wrote:
                              Bruce, My understanding is that, if designed to be entirely immutable
                              and containing no events, then there is almost no visible difference
                              between a class and a struct.

                              Apparently so. I'm trying to think of differences in behaviour between
                              an immutable class and a struct, and I can't. Of course, it's Monday
                              morning. I could be wrong.

                              One would have to overload == appropriately (and, one presumes, the
                              other mathematical and comparison operators), but apart from that I
                              can't think of any hitches. Of course, the temptation with a class
                              would be to make it mutable, but that's just a temptation, not a given.

                              The struct is primarily a speed-optimization - access to stack-variables
                              is
                              much faster.

                              I wouldn't state that as the primary speed benefits of structs. I
                              consider the primary speed benefit of structs being that they don't
                              need to be garbage-collected. So, if you are doing extensive
                              calculations that involve the creation of myriad intermediate results
                              then structs are a better choice because objects created on the heap
                              have to be GC'd.

                              However, this is only one consideration in whether to make something a
                              struct or a class, and not even the most important. The most important
                              consideration, IMHO, is whether the thing you want to create displays
                              _value semantics_. There are lots of discussions in this newsgroup
                              about struct vs class and value vs reference semantics.

                              Hence, structs should only contain other valuetypes.

                              No, I disagree. For example, I have a struct called a Measure, which
                              contains a decimal quantity and a unit of measure. UnitOfMeasure is a(n
                              immutable) reference type. I think that our disagreement on this point
                              goes back to the speed benefits of structs: I see storage on the stack
                              as a side-effect of using structs, not as a motivation for using
                              structs, and so I don't see anything wrong with structs that contain
                              references. Of course, structs that contain references to _mutable_
                              objects can lead to some awfully puzzling, nearly-unpredictable
                              behaviour, so I wouldn't recommend that. :-)

                              Comment

                              Working...