-
October 8th, 2014, 03:06 PM
#1
Should a type for working with fractions be a class or a struct?
Folks,
I’m making a C# type for working with fractions, and trying to follow best practices. My question is: should a type like this be a class (reference type) or a struct (value type)?
Here’s what I’m thinking.
- Fraction is a kind of a number, which makes me think that it should be a value type, and therefore a struct.
- System.Numerics.Complex has some similarities with a fraction type. Both represent a kind of a number. Both are small with only 2 numeric fields. System.Numerics.Complex is a stuct.
At the same time, I’ve found a couple of existing articles on CodeProject, which describe Fraction types. Both of them are classes.
The authors don’t explain why they chose to declare classes rather than structs. Something like that makes me think that there may be something that I don’t understand that was fairly obvious to them.
Any suggestion, insight or reference is really appreciated!
Cheers,
- Nick
P.S. For the most part, I work mostly with C and C++, where I have fine control over things like const, pointers, references. Of course, that comes at a risk of having nasty pointer-related bugs.
Last edited by kender_a; October 8th, 2014 at 03:22 PM.
-
October 8th, 2014, 05:22 PM
#2
Re: Should a type for working with fractions be a class or a struct?
i would much more lean towards struct since its math focused
it is by its own definition dealing with values "fractions"
alternatively static class or public sealed class / static methods
in truth its more dependent on how the class needs to be used
value or reference type is a bit of a oversimplification in this regard
your really talking about copy semantics stack or heap and boxing considerations
however the reality is
these concerns are very usage specific probably to much so to be determinable until the struct or class is put to the test of usage
i would refer you to this article by anders hejlsberg scrolling down
to the section on value types sheds some light on the question
http://www.artima.com/intv/choicesP.html
by my understanding
structs can at local scope be created droped on the stack then pop-ed off when done extremely efficiently
value types n structs though can end up being boxed then must be un-boxed which is not so good
to give a real world example
xna was used for the xbox
here performance was critical - the xbox has very low gc tolerance
so they used struct for all the Vector Matrix Rectangle class's ect...
this allowed for people to write basically zero garbage applications
(or rather applications that had zero garbage collections) ,
however it also allowed people to write applications that would box unbox the structs very bad on the xbox, if they were unaware of how the gc worked.
but that same app on the pc were this pressure was not so severe the bad might be unoticable
Last edited by willmotil; October 8th, 2014 at 05:42 PM.
-
October 12th, 2014, 01:21 AM
#3
Re: Should a type for working with fractions be a class or a struct?
Thank you for the insight. I went ahead and created a struct and ran into the following problem.
I can't have an explicit parameterless constructor. I can't have an instance field initializer like int m_denominator = 1;
At the same time, the denominator can't be zero. Is it possible to initialize the denominator to 1 when the implicit constructor new Fraction(); is used? Is it possible to suppress the implicit parameterless constructor, and to prevent it from ever being called?
The only solution I can think of at the moment, would be to implement the handling of the indeterminates (infinity and NaN) in this class. But that's a can of worms. [Could be a fun little can of worms, though... After all, this is a recreational programming effort.]
I'm sure that I'm not the first one to run into an initialization issue like this.
Last edited by kender_a; October 12th, 2014 at 01:26 AM.
-
October 12th, 2014, 09:00 AM
#4
Re: Should a type for working with fractions be a class or a struct?
ok so i thought this was a interesting point
i was looking for a way to get around this concern reasonably
however after reading this old post from 5 years back
which addresses nearly all the exact same points to a fraction class
http://stackoverflow.com/questions/3...-struct-in-net
im going to conclude which is better is not clear without a test case
while ideologically struct would be correct
due to technical reasons
c# wants exclusive rights to a struct's default constructor
ill point to this random guys quote which brings clarity to a important point
A struct is a value type and a value type must have a default value as soon as it is declared.
(this maybe the most important behavioral difference to remember with a struct)
MyClass m;
MyStruct m2;
If you declare two fields as above without instantiating either, then break the debugger, m will be null but m2 will not. Given this, a parameterless constructor would make no sense, in fact all any constructor on a struct does is assign values, the thing itself already exists just by declaring it. Indeed m2 could quite happily be used in the above example and have its methods called, if any, and its fields and properties manipulated!
in essence you cannot overide a c# struct default constructor
because
just declaring a struct m2; is equal to calling its default constructor as well
the reasons are not perfectly clear... and its counter intuitive
this is also similar to the behavior on property's with automatic get; set;
and that's how it is in c# so,,,
this would pose a real problem for the denominator returning a 0
one thing you would need to prevent divide by 0
is some access restriction via a property for example
in combination with a check
that the denominator is not returning or being set to zero in all case's
something akin to this, though im not sure i like this idea
a check on every call to get the denominator
that sort of works against the benifit of using the stuct in the first place
Code:
public struct Frac
{
private int numerator;
private int denominator;
public int Numerator
{
get { return numerator; }
set { numerator = value; }
}
public int Denominator
{
get { if (denominator == 0) { denominator = 1; } return denominator; }
set { denominator = value; }
}
}
for that reason a class may actually be a better solution
because now its even more so a matter of opinion
until it can be proven in a usage context which is the better choice
Last edited by willmotil; October 12th, 2014 at 09:25 AM.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|