473,915 Members | 5,967 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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.

Oct 28 '06 #1
37 4036
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

<Jo********@hot mail.co.ukwrote in message
news:11******** **************@ 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.

Oct 28 '06 #2
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.

Oct 28 '06 #3
<Jo********@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 - <sk***@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
Oct 28 '06 #4

Jo********@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.

Oct 28 '06 #5
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.
Oct 30 '06 #6
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.
Oct 30 '06 #7
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:
Jo********@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.
Oct 30 '06 #8
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:
http://www.yoda.arachsys.com/csharp/memory.html

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" <ma***********@ gmail.comwrote in message
news:11******** ************@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:
>Jo********@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.

Oct 30 '06 #9

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.

Oct 30 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
4665
by: Kilana | last post by:
I see this all the time in code: typedef struct a_struct { ... }differentName, *differentNamePtr; I understand how I can use it, but could someone tell me why the above is
2
11273
by: SACHIN | last post by:
I have this class as part of a Consol application. using System; namespace Bugreport { /// <summary> /// This class tries to use the Class/Struct combination. /// </summary> class Class1 {
4
31585
by: Steve | last post by:
I'll be the first to admit, I'm not entirely clear on the appropriate usage of either. From what I am reading in my books, a Struct and a Class are pretty much the same, with the difference being, a Class can have private and protected members, but a Struct everything is Public by default. I laymans terms what would be an appropriate reason to choose a Struct over a Class? So why would one want to choose a Class over a Struct.
15
9100
by: Steven T. Hatton | last post by:
The following may strike many of you as just plain silly, but it represents the kind of delelima I find myself in when trying to make a design decision. This really is a toy project written for the purpose of learning to work with C++. It therefore makes some sense for me to give the situation the amount of consideration presented below. To be quite honest, I'm amazed at the amount there is to say about such a seemingly simple...
15
3797
by: bugzilla | last post by:
hi,all, I have a C++ program need to convert to c language to be used in a emabedded system. the problem is that the original code was writtern in C++ language with Parent class and some child class. How can I invert these C++ code into pure c code by using struct in C language? Can somebody give me any ideas? thanks. For example, how to conver the following code into pure c code?
3
1922
by: Karl M | last post by:
Hi everyone, I just notice some strange behaviors on the MS C++ compiler regarding struct default constructor, see the example bellow: struct MyStruct { int a; }; class MyClass { public:
4
4037
by: DaHool | last post by:
Hi there !!! I browsed around the Internet in search for a solution of a little difficult problem i have in VB.NET.... However, i cannot find a suitable anwser anywhere, so i thought i'll give it a try here... Okay, here's the deal: I am trying to read from unmanaged memory with a class type struct, this
5
6096
by: jwright | last post by:
I have decided to use a struct to collect my data. The input file is comma dilineated between almost all of the fields. Here is the code I have so far and a sample input and output file. #include <fstream> #include <iostream> #include <iomanip> using namespace std; struct pyrll
1
2275
by: stromhau | last post by:
Hi, I have made a few classes in c++. They somehow cooperate doing some 3d stuff. Basically it is a moving camera acting as a flight, i have placed a lot of objects around the scene together with a b-spline surfcae. The problem class is the polygon class. this class read 3d files generates faces, edges and so on. here are two of the building blocks(structs) struct FACE{
2
2311
by: Ninereeds | last post by:
I'm messing around with using mixin-layers (look for papers by Yannis Smaragdakis and Don Batory) to define data structures. One issue is that nodes tend to have pointers to other nodes - the pointers have to point to the full node type, and have to be referenced before that full node type is known. One solution is to use the 'fixpoint construction' to get an apparent circular dependency... class c_Final : public c_Layer2< c_Layer1...
0
10039
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
11354
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10923
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9732
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
8100
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5943
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4778
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4344
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3368
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.