How to avoid assignments of multiple arguments passed to constructor - c#

If i have a class in c# containing many variables that needs to be initialised in a constructor e.g.
public class AnyClass
{
private int Var1;
private int Var2;
...
private int varN;
public AnyClass(int InVar1,int InVar2,...,InVarN)
{
Var1=InVar1;
Var2=InVar2;
...
VarN=InVarN;
//
//Code
//
}
}
Is there a way to avoid the intermediate variables InVar1, InVar2 etc in such a way that the arguments passed to the constructor are automatically mapped to the variables contained in the class.

Not at present, C# 6 may include it.
This is what is may look like
Before
public class Point {
private int x, y;
public Point(int x, int y)
this.x = x;
this.y = y;
}
}
After
public class Point(private int x, private int y) {
}
If you don’t mind having properties with a public setter, you can use Object initializers. E.g.
Cat cat = new Cat { Age = 10, Name = "Fluffy" };

Related

Why is this nested struct creation slower than un-nested?

I've been benchmarking some C# struct creation, and I've been surprised to find that creation of a nested struct is significantly slower than the un-nested version. I would have expected the JITter to basically produce the same assembly for a flat and nested structure, but this appears to not be the case.
Does anyone have an explanation for why the struct construction in my test code below doesn't get optimized down to just writing the 3 doubles? It seems to (if I'm reading the assembly correctly) zero and create a temporary memory location before writing the values to the final location - presumably actually creating a temporary copy of the nested struct.
And in the follow-up, is there a way to avoid this extra work such that the nested struct has similar creation speed to the un-nested one?
public class StructBenchmarks
{
public struct Vector3_dp
{
public Vector3_dp(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
public double X;
public double Y;
public double Z;
}
public readonly struct ContainsVector
{
public ContainsVector(double x, double y, double z)
{
m_vector = new Vector3_dp(x, y, z);
}
public ContainsVector(Vector3_dp input)
{
m_vector = input;
}
private readonly Vector3_dp m_vector;
}
private ContainsVector m_vector1;
private ContainsVector m_vector2;
private Vector3_dp m_vector3_dp1;
private Vector3_dp m_vector3_dp2;
// 0.2ns
public void Vector3_dp_Construction()
{
m_vector3_dp1 = new Vector3_dp(20, 30, 40);
}
// 3.8ns
public void Vector_Construction()
{
m_vector1 = new ContainsVector(20, 30, 40);
}
// 3.8ns
public void Vector_ConstructionFromVector3_dp()
{
m_vector1 = new ContainsVector(m_vector3_dp1);
}
// ~0ns
public void Vector3_dp_Copy()
{
m_vector3_dp1 = m_vector3_dp2;
}
// ~0ns
public void Vector_Copy()
{
m_vector1 = m_vector2;
}
}
And SharpLab link: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8BYAKAAJLyABAZhoCZyBlDKAVzAwCEYA7MAAt82KAGtcZKuQDeU6VTrlcbThnIA1GF2i0A+gBMADvIWzTZxfS06o+4wAoDEdsAA2McgjTlnrj+QAnj5+7p4AXgCUFpbmFLGWABrkALxeANwxCZQAmqlBmfHZ0gBa+eGFxeQAvmRZZkqhAYmVxY0uYeQ5rdnt/p4lPQq1pPU09LDYznxugcqqXOQAwhB8GNgAlny4NhjQY3JFCUora5vbu9BOHQHevjeewff95FFj0odV0vh6AG7aeyg+T4MAA7poAbpDEYHHcnlEhrERu8rMtVustjtIVAHJc7NDyFsjOwMNEjrFPl9KD9/rZ8kSSYjLMjyZYjFANr9sBhPJNprMIbZ7EZyDTsUzKCzYuzOdzPKcMRdsaK/tiAIwS8gyrk8tFnTF4lW0wEMQpjbVywWA4VG7HCjXmjk6zx4m1ioXQ011VmUAD0vvIAAYAHQMbZjJTUFBWqHGPSnFQcLgbVYOMkUlHU1Ue4xq4FgmP4xwMQM+Wil8goQORTVSyz+8i0YMADnDPvGNGjePjq0TahTfDTB0zttsebSIPBCvOWNsDhLZYrVZrYzrZgbTdbknbka72J72wWGAHADEoBB8K7oUP25Tsu7AePyJO9YrZ4CHA/Y0Y1Sv22uFF3QthR7IxAhvDN22+bNrWhJ8vyLIwvX/MYI3oKNC1A8D00sO8EgQ+CYOgZCkQsEYgA=

Initializing obj with/without default values

In c#:
public class SomeClass
{
int x;
int y;
SomeClass (int x, int y)
{
this.x = x;
this.y = y;
}
}
Is there easy way to make new SomeClass without setting x and y instead to
have default values for them and if I set values to set them else to have the
default values?
Sure, with C#6 you can use auto-implemented properties:
public class SomeClass
{
public int X { get; } = 123;
public int Y { get; } = 456;
public SomeClass(){ }
public SomeClass(int x, int y)
{
this.X = x;
this.Y = y;
}
}
Of course you need a parameterless constructor.
If you instead mean default values of the type, that is done automatically(0 for numerical types).
Sure...
new SomeClass(default(int), default(int))
Or, more simply:
new SomeClass(0, 0)
The default value for int is always 0. So even if you define it with a parameterless constructor:
public SomeClass() { }
Those int class members would still default to 0.
You need to define a parameterless constructor:
public class SomeClass
{
int x;
int y;
public SomeClass {}
public SomeClass (int x, int y)
{
this.x = x;
this.y = y;
}
}
When you create an object like:
var someClass = new SomeClass();
both x and y would be initialized using their default values, which is 0.
If you don't want to do so, you could handle this by passing to the constructor that you have already declared the default values of x and y, as already David has pointed out.
Use a parameterless constructor.
Since the instances have to be created somehow using a new keyword, you can use a parameterless constructor inside your class.
public SomeClass ()
{
x = 0;
y = 0;
}
A default constructor would do that automatically.
You can use optional parameters in the constructor.
Read more on named and optional parameters.
public class SomeClass
{
// You can also write this as
// public SomeClass(int x=default(int), int y=default(int)) if you do
// not want to hardcode default parameter value.
public SomeClass(int x=0, int y=0)
{
this.X = x;
this.Y = y;
}
}
You can call it as
void Main()
{
SomeClass a = new SomeClass();
SomeClass b = new SomeClass(1);
SomeClass c = new SomeClass(2,4);
}

Calling a parent class from a subclass

class experiment
{
int xCoord = 0;
int yCoord = 0;
public experiment(int x, int y) {
this.xCoord = x;
this.yCoord = y;
}
}
class result :experiment{
int zCoord = 0;
public result(int z) : base(x,y)
{
this.zCoord = z;
}
}
Can anyone help me solve this simple problem. I'm having an error base(x,y) it says the name 'x' does not exists in the current context and also goes for the y.
x and y are local fields to class experiment they are not visible in inherited class, you may call the base constructor with default values like:
public result(int z) : base(0,0)
Also please follow General Naming Conventions from Microsoft, so the class names begins with upper case character.
EDIT:
It would be better if your child class has a constructor to receive parameter x and y, and the it calls the base class constructor with those values like:
public result(int x, int y, int z) : base(x,y)
{
this.zCoord = z;
}
There is no x,y in constructor of result class.
You pass to your constructor z but tell your base constructor to recieve x and y. Though there are no x and y at that time.
Try this:
public result(int z, int x, int y) : base(x,y)
{
this.zCoord = z;
}
Or set fix values (no variables):
public result(int z) : base(0, 0)
{
this.zCoord = z;
}

Creating a generic list of objects in C#

By way of an intro, I'm creating a basic Quadtree engine for personal learning purposes. I'm wanting this engine to have the capability of working with many different types of shapes (at the moment I'm going with circles and squares) that will all move around in a window and perform some sort of action when collision occurs.
Here are my shape objects as I have them so far:
public class QShape {
public int x { get; set; }
public int y { get; set; }
public string colour { get; set; }
}
public class QCircle : QShape {
public int radius;
public QCircle(int theRadius, int theX, int theY, string theColour) {
this.radius = theRadius;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
public class QSquare : QShape {
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
Now my question is, how do I create a generic list (List<T> QObjectList = new List<T>();) in C# so I can have one list containing all these various shapes that may have different properties (e.g., QCircle has the "radius" property while QSquare has the "sideLength" property)? An example of implementation would be helpful as well.
I just know that there is a stupidly obvious answer to this question but I'd appreciate any help anyway. I'm trying to get back into C#; it has obviously been a while...
You need to use downcasting
Store the objects in a list with the base class
List<QShape> shapes = new List<QShape>
You can then upcast the object safely if you know what it is e.g.
if(shapes[0] is QSquare)
{
QSquare square = (QSquare)shapes[0]
}
You can also implicitly downcast objects
QSquare square = new Square(5,0,0,"Blue");
QShape shape = square
For more information read the Upcasting and Downcasting sections here
You should implement an Interface. For example
public interface IHasLength
{
int Length;
}
Then in the implementation you can do
public class QSquare : QShape, IHasLength {
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
public int Length { get { return sideLength; } }
}
public class QCircle : QShape, IHasLength {
public int radius;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
public int Length { get { return radius; } }
}
FInally, in your list:
List<IHasLength> shapesWithSomeLength = new List<IHasLength>();
Now your list can hold ANYTHING that implements IHasLength whether it's a QCircle, QShape, or even a QDuck if you want as long as it implements IHasLength.
Is this what you want?
public class QShape
{
protected QShape() { }
public int x { get; set; }
public int y { get; set; }
public string colour { get; set; }
}
public class QCircle : QShape
{
public int radius;
public QCircle(int theRadius, int theX, int theY, string theColour)
{
this.radius = theRadius;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
public class QSquare : QShape
{
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour)
{
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
class Program
{
static void Main(string[] args)
{
List<QShape> list = new List<QShape>();
list.Add(new QCircle(100, 50, 50, "Red"));
list.Add(new QCircle(100, 400, 400, "Red"));
list.Add(new QSquare(50, 300, 100, "Blue"));
foreach (var item in list.OfType<QCircle>())
{
item.radius += 10;
}
foreach (var item in list.OfType<QSquare>())
{
item.sideLength += 10;
}
}
}
You could store them in a List<QShape> but this would mean that you could not access type-specific properties.
Generally, you might approach this by providing a common interface in your base class, and overriding behaviour in subclasses. In this way, a common interface can hide a diverse bunch of behaviours. For instance a Grow method could hide the complexities of growing items of different shape and could be called without explicit knowlege of the shape upon which it is operating.
public abstract class QShape {
public abstract void Grow(int amt);
}
public class QSquare : QShape {
private int sideLength;
public override void Grow(int amt)
{
sideLength+=amt;
}
}
public class QCircle : QShape {
private int radius;
public override void Grow(int amt)
{
radius+=amt;
}
}
I feel like i'm missing something but...
List<QCircle> circleObjects = new List<QCircle>();
and
List<QSquare> squareObjects = new List<QSquare>();
will work perfectly well.
EDIT:
Ah, I didn't understand what was being asked.
Yes, as your QCircle and QSquare classes inherit from QShape, you can just do.
List<QShape> shapes= new List<QShape>();
It's worth noting that if you want to access the radius property of all the QCircle's in that list, then you are going to have to filter the list based on type.
You can use Ian Mercer's comment List<QShape>
And here's how you would fill it:
List<QShape> shapes = new List<QShape>();
QCircle circle = new QCircle();
shapes.Add(circle);
To unbox it:
QCircle circle = (QCircle) shapes[0];
If you need to call a method off the base class, no need to unbox, just use it.
Storing
You're already on the right track with your class definitions. What you have to do is make a List of the superclass (in this case, QShape), which will be able to hold all of your shapes.
Here's an example of how you would make it:
List<QShape> objects = new List<QShape>();
objects.add(new QCircle(...));
objects.add(new QSquare(...));
Accessing
The problem here is differentiating what is what once everything is in the list. That's done with the getType() and typeof() methods of C#. (Jon Skeet has an excellent answer about how to do this). Basically, it looks like this:
if(objects.get(some_position).getType() == typeof(QCircle))
QCircle circle = objects.get(some_position);
else if(/* like above with QSquare */)
QSquare square = objects.get(some_position);
After you do this, you can resume using your objects like normal. But if you try accessing them from the list, you can only use the methods and variables that QShape has, as every object put in the list will be cast to it.
public Class abstract Base<T>
{
public abstract List<T>GetList();
}
then do this
public class className:Base<ObjectName>
{
public override List<T>GetList()
{
//do work here
}
}

Problem with constructors and inheritance in C#

I am having the following problem:
public class A {
public A(X, Y, Z) {
...
}
}
public class B : A {
public B(X, Y) : base(X, Y) {
//i want to instantiate Z here and only then pass it to the base class!
}
}
How can I solve this problem? Is there a way?
The common solution is to call a static method belonging to the type that can calculate the value of the parameter to be passed to the base constructor.
For example:
public B(int x, int y)
: base(x, y, CalculateZ(x, y))
{
}
// You can make this parameterless if it does not depend on X and Y
private static int CalculateZ(int x, int y)
{
//Calculate it here.
int exampleZ = x + y;
return exampleZ;
}
Do note that CalculateZ cannot be an instance method, because the this reference is not available in constructor initializers.
From the language-specification 10.11.1 Constructor initializers:
An instance constructor initializer
cannot access the instance being
created. Therefore it is a
compile-time error to reference this
in an argument expression of the
constructor initializer, as is it a
compile-time error for an argument
expression to reference any instance
member through a simple-name.
EDIT: Changed 'instance' to 'static' in the description.
You need to calculate Z before the constructor itself gets called. If it's simple you can use an inline expression, else you'll need to define a helper function.
Using a helperfunction:
public class A {
public A(X x, Y y, Z z) {
...
}
}
public class B : A {
private static Z calculateZ()
{
}
public B(X x, Y y) : base(X, Y, calculateZ()) {
}
}
Without helperfunction:
public B(X, Y) : base(X, Y, X+Y) {
}
public abstract class A {
public A(X, Y) {
...
}
public abstract Z TheVariableZ{get;set;}
}
public class B : A {
public B(X, Y) : base(X, Y) {
//i can only calculate Z here!
}
public override Z TheVariableZ{//implement it here}
}
And if you can't make A abstract, just mark the property as virtual
Possibly this:
public abstract class A {
public A(X, Y) {
CalculateZ();
}
abstract void CalculateZ();
}
public class B : A {
public B(X, Y) : base(X, Y) {
}
override void CalculateZ()
{
... Calculate here.
}
}

Categories

Resources