namespace Area
{
public class Rectangle
{
private double length;
private double width;
public Rectangle() { }
public Rectangle(double length, double width)
{
this.Length = length;
this.Width = width;
}
public double Length
{
get
{
return length;
}
set
{
length = value;
}
}
public double Width
{
get
{
return width;
}
set
{
width = value;
}
}
public double getArea()
{
return width * length;
}
public double getPerimeter()
{
return 2 * width + 2 * length;
}
public double getDiagonal()
{
return Math.Sqrt(Math.Pow(width, 2) + Math.Pow(length, 2));
}
I want to make sure I am using best practices with C# Objects. Please use the above example for reference.
1. Is it necessary that I type the first empty Constructor? In class the Instructor always did on each program but never really gave an answer as to why.
public Rectangle() { }
2. Inside my Custom Constructor Visual Studio generates it like this:
this.Length = length;
I know that the "this" keyword is not necessary the way it is typed, but in class the instructor sometimes changed it to lowercase like this:
this.length = length;
But sometimes he didn't change it. Which way is best practices?
And is the left side the actual Property? And then the right side is the field?
So it is, Property equals field?
3. And finally, in this case cant I just type my properties as:
public string Length { get; set; }
instead of the way Visual Studio generates with the return and value.
Sorry for the long post, I am tired of getting different answers at school and want one final answer on this, thanks.
I would suggest that your class look like this:
public class Rectangle
{
public Rectangle(double length, double width)
{
this.Length = length;
this.Width = width;
}
public double Length { get; set; }
public double Width { get; set; }
public double Area { get { return this.Width * this.Length; } }
public double Perimeter { get { return 2.0 * (this.Width + this.Length); } }
public double Diagonal { get { return Math.Sqrt(Math.Pow(this.Width, 2.0) + Math.Pow(this.Length, 2.0)); } }
}
See here for why you might want a blank constructor. To summarize, adding a non blank constructor will stop the compiler from generating a blank one for you (the compiler assumes that if you wanted it, you would have defined it with the other constructors you wrote). Some things, like serialization, will not work without a blank constructor, so that's a reason you might want to add one.
In my career, I've mostly seen people avoid using this in constructors. Maybe avoid isn't the right word, but unless it's unclear, they just didn't bother to put it there. This is probably too minor an issue to lose any sleep over.
UPDATE based on some of your comments
When you write
public Rectangle(double length, double width)
{
Length = length; //parameter length assigned to field length by virtue of property Length
}
you are assigning the parameter length to the property Length, which itself assigns the passed in value to the length private field. Since C# is case sensitive, Length and length aren't confused in any scenario, and you don't need to specify the this keyword.
Inside a method with a parameter called length, the language is assuming that you are referring to the parameter of the method when you type length. So if you try to do something like this:
public Rectangle(double length, double width)
{
length = length; //warning: Assignment made to same variable; did you mean to assign to something else
}
The compiler doesn't try and assume that you are assigning the property to the field, and this is just assigning the length parameter to itself. In this case, you would use the this keyword to tell the compiler that you want to assign the parameter length to the private field length, like this:
public Rectangle(double length, double width)
{
this.length = length; //no warning
}
END UPDATE
Yes, you could declare the property as just Property {get;set;}. This feature is only from C# 3.0 and is called auto-implemented properties (see this link). Before that you had to provide the implementation yourself.
I changed my class to this:
public class Rectangle
{
public Rectangle(double length, double width)
{
Length = length;
Width = width;
}
public double Length { get; set; }
public double Width { get; set; }
public double getArea()
{
return Width * Length;
}
public double getPerimeter()
{
return 2 * Width + 2 * Length;
}
public double getDiagonal()
{
return Math.Sqrt(Math.Pow(Width, 2) + Math.Pow(Length, 2));
}
}
If anyone has any other feedback on anything above that you recommend to change please give it, I catch on very fast and want to learn the correct way.
Related
The title of the question may seem confusing but bear with me, I'll try to explain the problem as clearly as possible.
So I was just studying about the Liskov substitution principle from a course and the lecturer has given an example showing logical errors we can solve using this principle. Hence, the example shown below is the problem with the logical error.
(Note: Please read the whole question even if you don't know/find out this example has nothing to do with Liskov principle as I've mentioned that above. I've just kept this in question for reference, just in case someone bothers to answer that you're doing it the wrong way)
Rectangle is the parent class
class Rectangle
{
public int Width { get; set; }
public int Height { get; set; }
public Rectangle()
{
}
public Rectangle(int width, int height)
{
Width = width;
Height = height;
}
public override string ToString()
{
return $"{nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
}
}
Square class
class Square : Rectangle
{
public new int Width
{
set { base.Width = base.Height = value; }
}
public new int Height
{
set { base.Width = base.Height = value; }
}
}
Just a simple Caller
private void Caller()
{
Rectangle rc = new Square(); //Upcasting here
rc.Width = 4;
Console.WriteLine($"{rc}"); //Now here the o/p is **Width: 4, Height: 0** which is correct
//But when we use object initializer as shown below
Rectangle rcTwo = new Square { Width = 4 };
Console.WriteLine($"{rcTwo}"); //the o/p is **Width: 4, Height: 4**
}
Now aren't we just initializing the object in a different way? Why is the O/P supposed to differ in that case. I thought that object initializer is just an syntactical sugar when when we to create an object and initialize it's properties in comparison with the traditional approach.
You are right that it's syntactical sugar. But you have to think of the order of operations: assignment is done last, after all the operations on the right of the equals sign. So your second version with initialiser is the same as:
Square square = new Square();
square.Width = 4;
Rectangle rcTwo = square;
i.e. I've got a class Box with properties length, height, width and constructor "Box(int witdth, int height, int length)". Got an inhereted class ProductBox with property Name.
I've also got a .csv file which I parse to ProductBox with FileHelpers library, so my constructor's empty.
For now I can't inherete ProductBox from Box, because Box has not-empty constructor, and in FileHelpers the constructor's empty. Is there a way to inherete ProductBox from Box?
class Box
{
int Width;
int Height;
int Length;
public Box(int width, int height, int length)
{
this.Width = width;
this.Height = height;
this.Length = length;
}
}
class ProductBox : Box
{
string Name;
int Width;
int Height;
int Length;
public static ProductBox[] GetInfo(string filePath)
{
var engine = new FileHelperEngine<ProductBox>();
var result = engine.ReadFile(filePath);
return result;
}
}
No.
If your base class provides a parametered constructor, you can't provide a parameterless one in a derived class unless you redefine the base class to also have a parameterless constructor. Where would the values come from?
If your base was actually a struct instead, it would be possible because of the default parameterless constructor defined by structs.
You could chain your constructor as described by hl3mukkel, where your derived class passes the constructed values. You could also do something like this:
class ProductBox : Box
{
string Name;
public ProductBox()
:base(0,0,0)
{
}
}
If you wanted to provide the defaults yourself.
From a design perspective, I think you are going about it the wrong way. While you might be able to hack something together to solve your constructor problem, you are trying to use the Box class for two incompatible uses. Instead you should have two separate classes.
FileHelpers is a library for describing csv files so that you can import them easily. You should have a BoxFileSpec for describing your file. It's really not a proper C# class - it may have: dummy fields to represent unused columns; lots of attributes [FieldNullValue], [FieldQuoted], [FieldConverter]; etc. It works best with public fields (a FileHelpers limitation which is not C# best practice), etc. It is a convenience syntax for describing the import file. It should not include any logic or special constructors.
Then you can have a clean best-practices Box class which has your specialized constructors and additional logic, properties, methods, whatever.
Then you use a FileHelperEngine<BoxFileSpec> to read the records into an array and map it to an enumerable of Box (via Linq or a library like AutoMapper).
Something like:
/// A 'real' class. Add methods, getters, setters, whatever.
/// FileHelpers doesn't use this class.
class Box
{
public int Width { get; set; }
public int Height { get; set; }
public int Length { get; set; }
public Box(int width, int height, int length)
{
this.Width = width;
this.Height = height;
this.Length = length;
}
}
/// A 'real' class. Add methods, getters, setters, whatever.
/// FileHelpers doesn't use this class.
class ProductBox : Box
{
public ProductBox(int width, int height, int length)
: base(width, height, length)
{ }
public int Name { get; set; }
}
/// This is the class FileHelpers will use
/// This class describes the CSV file only. Stick to whatever
/// syntax conventions are required by FileHelpers.
[DelimitedRecord(";")]
class ProductBoxFileSpec
{
[FieldQuoted(QuoteMode.OptionalForRead)]
public int Width;
[FieldQuoted(QuoteMode.OptionalForRead)]
public int Height;
[FieldQuoted(QuoteMode.OptionalForRead)]
// Handle non-US formats such as , decimal points
// convert from inches to centimetres?
// you get the idea...
[FieldConverter(MyCustomizedLengthConverter)]
public int Length;
[FieldOptional]
public string SomeDummyExtraCSVColumn;
}
class Program
{
static void Main(string[] args)
{
var engine = new FileHelperEngine<ProductBoxFileSpec>();
var productBoxRecords = engine.ReadFile(filePath);
var productBoxes = productBoxRecords
.Select(x => new ProductBox(x.Width, x.Height, x.Length) { Name = x.Name });
}
}
Yes, if it inherits from it you can just do constructor chaining
public class Box
{
int Width;
int Height;
int Length;
public Box(int width, int height, int length)
{
this.Width = width;
this.Height = height;
this.Length = length;
}
}
public class ProductBox : Box
{
string Name;
public ProductBox(string Name, int width, int height, int length)
: base(width, height, length)
{
this.Name = Name;
}
public static ProductBox[] GetInfo(string filePath)
{
var engine = new FileHelperEngine<ProductBox>();
var result = engine.ReadFile(filePath);
return result;
}
}
I noticed that in the Microsoft.Xna.Framework.Rectangle struct, there are plenty of properties that are just public int Bottom { get; } or public Point Center { get; }. I, for the life of me, can't figure out what's going on here. I've tried replicating this in some of my own structs, but I can't figure out how to give it a value in the first place without the set; keyword. What is it that the Rectangle struct is doing to {get;}?
The reason why the Rectangle.Bottom doesn't have a set is because it is a calculated value, Top + Height. If you would set that, what would you like to happen? Change the y position? Change the height? It is impossible to know. So you have to decide yourself and change the Top or Height based on what you actually want.
The idea of properties is not just to have a variable and set or get it. If it was we could just use public variables and that's it. Rather the idea is to allow validation and calculated properties.
public int Bottom
{
get { return Top + Height; }
}
As you can see, there is no need to set it to anything, since it will infer its value based on other values.
(Of course internally it will most likely not use the other properties, but rather the actual variables due to performance)
It means the underlying value that the property gives you access to cannot be set later on.. you can only "get" the underlying value.
When you instantiate a Rectangle, you have to pass it a few values:
public Rectangle (int x, int y, int width, int height)
My guess (without looking at the source code) is that the property values (Center, Bottom, etc) are all set in the constructor. You can't alter them later on.. either look for another property to set (i.e. X or Y), or create a new Rectangle based on the existing one.
var newRect = new Rectangle(oldRect.X, oldRect.Y, oldRect.Width, oldRect.Height);
For comparison, here's a portion of the source code from the System.Drawing.Rectangle struct, which is probably fairly close to what you're dealing with. Notice that you can set certain values via the constructor, which are then stored in private variables, and are accessible (but only changeable in some) properties.
public struct Rectangle
{
public static readonly Rectangle Empty = new Rectangle();
private int x;
private int y;
private int width;
private int height;
public Rectangle(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int X
{
get { return x; }
set { x = value; }
}
public int Left
{
get { return X; }
}
public int Y
{
get { return y; }
set { y = value; }
}
public int Top
{
get { return Y; }
}
...
...
}
Consider the following:
private int myVar;
public int MyProperty
{
get { return myVar; }
}
Here you see an example, taken directly from Visual Studio's C# snippets, showing how to implement a get-only property. You need to set the backing field, but it cannot be done via the property because this property is said to be a read-only property or a property with no setter method. The purpose of such properties is to make a contractual statement about your object "this property cannot be set."
This is similar to having a private setter, however, you cannot enforce access modifiers in an interface definition. Therefore, this syntax serves a specific purpose when defining data contracts and object interfaces, and that is to say "this property cannot be set, by contract, and no subclass may expose a public setter as part of this contract."
As an aside, you can circumvent access modifiers using reflection, but this is not the common case (and 99% of the .NET developers out there are probably unaware of this fact.)
Typically backing fields are set via a constructor, via reflection, or as part of object initialization.
This is also core syntax, it forms the basis of modern syntactic sugar. Consider the following property definition:
public int MyProperty { get; set; }
This is entirely syntactic sugar, and not actually valid for a C# 1.0 compiler. Today at compile time a backing field is generated on your behalf. Thus, the following syntax is only valid for interface definitions (as it would never return a meaningful value otherwise.)
public int MyProperty { get; }
The above is an (invalid) attempt to create a read-only property using the newer auto-property syntax.
References:
When should use Readonly and Get only properties
Using a backing variable for getters and setters
Is it possible to access backing fields behind auto-implemented properties?
https://msdn.microsoft.com/en-us/library/bb384054.aspx
https://msdn.microsoft.com/en-us/library/w86s7x04.aspx
I have some C++ code that implements a basic Pixel class. Here's just a stub of the important bits I have:
// Pixel.h
template <class SizeType>
struct Pixel
{
public:
typedef SizeType Size;
Size R;
Size G;
Size B;
static Size Min;
static Size Max;
TPixel(Size R = Min, Size G = Min, Size B = Min);
};
#include "Pixel.impl"
// Pixel.impl
template <class SizeType> SizeType Pixel<SizeType>::Min = std::numeric_limits<Size>::min();
template <class SizeType> SizeType Pixel<SizeType>::Max = std::numeric_limits<Size>::max();
template <> float Pixel<float>::Min = 0;
template <> float Pixel<float>::Max = 1;
template <> double Pixel<double>::Min = 0;
template <> double Pixel<double>::Max = 1;
And in C# I'm trying to duplicate this:
struct Pixel<Size> where Size : struct
{
public Size R;
public Size G;
public Size B;
public static const Size Min; // What should I do here?
public static const Size Max;
}
Except I have no idea how I can include this Min / Max size into the type. I'd like to be able to have a uniform Pixel interface which allows you do things like clamping, adding, scaling, etc.
I'm running into a similar solution when I'm trying to deal with Vectors and Matrices of potentially arbitrary type. Can anyone advise me on how I can accomplish what the above C++ code is doing?
Unlike C++ template specialization, there is no such thing as specialization of a generic in .Net.
You can't initialize a T instance to anything but a T, unless you have a constraint, so you can't use a static constructor to try to work around the problem.
As far as I know, there is no constraint that allows you to specify only types that either are numeric types, or have conversions from numeric types.
I suggest you just make two different types of classes:
public struct PixelFloat
{
public float R { get; set; }
public float G { get; set; }
public float B { get; set; }
public const float Min = 0.0f;
public const float Max = 1.0f;
}
public struct PixelDouble
{
public double R { get; set; }
public double G { get; set; }
public double B { get; set; }
public const double Min = 0.0f;
public const double Max = 1.0f;
}
This is effectively the same thing anyhow, as this is what it would compile to under the covers. Other solutions won't buy you much compared to this, as you'll still have to type in the type: Pixel<double> Pixel<float>.
Also, in cases like this, I would suggest you use names that show that you're using types from your generic parameters. Size isn't obviously a generic parameter. TSize is. And TSize doesn't describe what the type does, it just describes how it varies. Instead you should name it something like TValue.
The only way to do this sort of thing would be to add an interface constraint to Size which requires Size to have Max and Min methods or something like that. Of course, the definitions would no longer be necessary in that case.
Assuming that what you are trying to accomplish is to do template specialization in C# generics, this is not possible.
Here is an MSDN link comparing the differences between the two but the highlights are:
C# does not support explicit specialization; that is, a custom implementation of a template for a specific type.
C# does not support partial specialization: a custom implementation for a subset of the type arguments.
You would have to do something like this:
static class Pixel
{
public static Size Min<Size>() where Size : struct;
public static Size Max<Size>() where Size : struct;
}
struct Pixel<Size> where Size : struct
{
public Size R;
public Size G;
public Size B;
}
And then call it like so:
Pixel<double> doublePixel;
var max = Pixel.Max<double>();
Does that work for you?
Something like this, maybe?
public struct Pixel<Size> where Size : struct
{
private enum DEF_TYPES
{
MIN,
MAX
}
private static Dictionary<Type, Dictionary<DEF_TYPES, object>> m_Defs = new Dictionary<Type, Dictionary<DEF_TYPES, object>>
{
{
typeof(float),
new Dictionary<DEF_TYPES, object> {
{DEF_TYPES.MIN, 0f},
{DEF_TYPES.MAX, 1f}
}
},
{
typeof(double),
new Dictionary<DEF_TYPES, object> {
{DEF_TYPES.MIN, 0d},
{DEF_TYPES.MAX, 1d}
}
}
};
private static Size GetValue(DEF_TYPES def_type)
{
if(!m_Defs.ContainsKey(typeof(Size)))
throw new ArgumentException("No default values for template " + typeof(Size));
if(!m_Defs[typeof(Size)].ContainsKey(def_type))
throw new ArgumentException("No default value '" + def_type + "' for template " + typeof(Size));
return (Size)m_Defs[typeof(Size)][def_type];
}
public Size R;
public Size G;
public Size B;
public static readonly Size Min = GetValue(DEF_TYPES.MIN);
public static readonly Size Max = GetValue(DEF_TYPES.MAX);
}
And used as:
Console.WriteLine(Pixel<float>.Max);
Console.WriteLine(Pixel<float>.Min);
Console.WriteLine(Pixel<double>.Max);
Console.WriteLine(Pixel<double>.Min);
And;
Pixel<double>.Min = 4;
Won't compile, as expected.
Not ideal, but it works.
Well I am learning properties and I am not sure about the following:
class X
{
private int y;
public X(int number)
{
this.Y=number; // assign to property
OR
this.y=number //?
}
public int Y;
{
get; set;
}
}
When you use auto-properties (get; set; or a variant thereof), the backing variable is not accessible. Those can, for the most part, be treated as simple variables, especially internally.
If you need to perform custom validation or mutation logic in the mutator, or otherwise have the need for an explicit backing variable, you cannot use auto-properties but have to write stub get and set methods yourself.
They do different things; I would do Y = number; and remove the (unused) field y. In an automatically implemented property, the compiler creates it's own field (with a horrible name that you can't see in C#) - you don't need to provide your own field. So:
class X
{
public X(int y)
{
Y = y;
}
public int Y { get; set; }
}
Other points: changed number to y to be clearer to the caller, and also you don't need this. since it isn't ambiguous (field vs parameter, etc).
Only assign to a field (private int y) inside the property representing that field (public int Y {get;set}). No where else in the class should the backing field be assigned to directly. Always do it through the property... yes even in the constructor. It follows from the do not repeat yourself (DRY) principle.
This is recommended because whenever in future you want to associate some behavior to be triggered by that assignment you only have a single place (the set accessor) to write code into.... not all the places where the field is assigned to !!
class X
{
private int y; //not strictly necessary but good for documentation
public X(int number)
{
Y = number;
}
public int Y { get; set; }
}
When you use autoproperties like:
public int Y;
{
get; set;
}
You don"t need a private property because it's autogenerated. so you class will be:
class X
{
public X(int number)
{
Y = number;
}
public int Y // no semicolon here, comment added for edit length
{
get; set;
}
}
Hope this helps
You have two choices :
class X
{
private int y;
public int Y
{
get { return y; }
set { y = value; }
}
public X(int number)
{
Y = number;
//equivalent to
y = number;
// but you should use the public property setter instead of the private field
}
}
or with auto-properties , it's even simpler :
class X
{
private int y;
public int Y
{
get; set;
}
public X(int number)
{
Y = number;
}
}
When not using auto-properties I always use the Property setter because there can or will be code in the setter that I need to be executed. This code could be a domain check or the raising of an event such as PropertyChanged.
A point I usually try to make about accessing backing variables:
Sometimes the public getter might contain complicated data validation,raising property changed events or some other complex code that is triggered when some external code changes it's value.
When changing that value internally (from inside the class), it might be a valid point to use the backing variable directly if your intention is to skip all the validation and events from the public setter. It's like saying "i'm the class instance, I know what I'm doing". This way the public setter is acting like a guard-dog, sanitizing external input, while I can still set the property internally to whatever I need.
class X
{
private int y; //not strictly necessary but good for documentation
public X(int number)
{
y = GetYValueFromDB(); //we assume the value from DB is already valid
}
public int Y {
get{ return y};
set {
if (ComplexValidation(value)
{
RaiseOnYPropertyChanged();
y = value;
}
}
}