Very basic exercise in Virtual functions - c#

Alright, so here's the exercise:
You must define three classes. One class named MyNum that contains a variable of type int. Second class called MyString, will be derived from MyNum and contains string. Third-class call MyType and returns a variable of type MyNum. Each class will be set to a constructor function and virtual function called Show. The constructor function of MyType receive a MyNum variable, whereas the function Show of MyType will run the Show function of MyNum.
Now, you need set two objects of type MyType and initialize them. Once an object type MyNum and once an object of type MyString.
Here's the code:
class MyNum
{
protected int num;
public MyNum(int num)
{
this.num = num;
}
public virtual void Show()
{
Console.WriteLine("The number is : " + num);
}
}
class MyString : MyNum
{
string str;
public MyString(string str)
{
this.str= str;
}
}
class MyType : MyNum
{
MyNum num2;
public MyType(MyNum num)
{
this.num2 = num;
}
public override void Show()
{
base.Show();
}
}
class Program
{
static void Main(string[] args)
{
}
}
I'm having the following error:
Error 1 'ConsoleApplication1.MyNum' does not contain a constructor that takes '0' arguments C:\Users\x\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs 23 16 ConsoleApplication1
Anyone knows why am I having this error? Thanks.

Since your class subclasses MyNum, it needs to be able to construct it. You don't have a default constructor, so you have to explicitly call it with a value.
For example:
// Since this is here, you're saying "MyType is a MyNum"
class MyType : MyNum
{
MyNum num2;
public MyType(MyNum num) // You need to call the base class constructor
// here to construct that portion of yourself
: base(42) // Call this with an int...
{
this.num2 = num;
}
The class MyString will need similar treatment. It will have to have a constructor that calls the base class constructor, too.
Note that, if the MyNum class had a default constructor (which could be protected), this wouldn't matter. Instead of calling these constructors, the other alternative is to do something like:
class MyNum
{
public MyNum(int num)
{
this.num = num;
}
// Add a default constructor that gets used by the subclasses:
protected MyNum()
: this(42)
{
}
Edit in response to comments:
If you want to override the base class constructor, try:
class MyType : MyNum
{
public MyType(int num)
: base(num)
{
}
public override void Show()
{
Console.WriteLine("The number [MyType] is : " + this.num);
}
}

MyString implicitely has a zero-arg constructor because you did not specify any constructor in that class. You could either declare a zero-arg constructor in the super class or declare a one-arg constructor in MyString.

MyString does not have a constructor, so it will use the one from the base class MyNum, which doesn't have a default one with no parameters.
MyString needs a constructor or you need a paramterless one in the base class.

Related

Base() and This() in constructors. (Chained constructors)

I have a question regards chaining constructors I read some question on StackOverflow and some c# articles but I cannot understand the topic fully. So I have a BaseClass that is inherited by DerivedClass. In the DerivedClass, I have no argument constructor but it's calling the base constructor using: base() and it also passing a value. Is this the primary purpose of the base keyword used in the constructor to pass a value to the inherited class from the derived one or is something more out there. And also in the derived class, we have a second constructor that takes 1 parameter and its using: this(). I can't understand why when I remove: this() from this constructor "VS" tells me "There is no argument given that corresponds to the required formal parameter "i" of BaseClass.BaseClass(int) ? Why I can't just have one argument constructor in the DerivedClass without using this()?
public class BaseClass
{
protected int _Num;
public BaseClass(int i)
{
_Num = i;
}
public int Num { get => this._Num ; set => _Num = value; }
}
public class DerivedClassA : BaseClass
{
private string _Name;
private int _AnotherValue;
public string Name { get => this._Name ; set => this._Name = value; }
public int AnotherValue { get => this._AnotherValue; set => this._AnotherValue = value; }
public DerivedClassA() : base(123)
{
_Name = "testing";
}
public DerivedClassA(int param2) : this() <-- Why i can't compile the program without the this() keyword here ?
{
AnotherValue = param2;
}
}
public class Program
{
public static void Main(string[] args)
{
DerivedClassA objA = new DerivedClassA(5);
}
}
I can't find a duplicate that exactly matches, so I'll provide an answer.
Imagine these classes:
public class Base
{
public Base()
{
}
}
public class Derived : Base
{
public Derived()
{
}
}
Try it online
When you initialize a derived class, you have to first initialize the base. In our example above, the Base class has a parameterless constructor, so the derived class can implicitly call it. If we add a base second constructor, this logic remains true, and the parameterless constructor will still be implicitly called:
public class Base
{
public Base()
{
}
public Base(int a)
{
}
}
public class Derived : Base
{
public Derived()
{
}
}
Try it online
But if we take away the parameterless constructor, Derived must now call the base constructor explicitly:
public class Base
{
public Base(int a)
{
}
}
public class Derived : Base
{
public Derived() : base(1)
{
}
}
Try it online
So what happens if we add an extra derived class constructor? Well, that also has to call the base class (either directly, or indirectly):
public class Base
{
public Base(int a)
{
// this method body is executed first
}
}
public class DerivedA : Base
{
public DerivedA(string name, int val) : base(val)
{
// this method body is executed second (last if you used this constructor, e.g. new DerivedA("hello", 1) )
}
public DerivedA() : this("test", 5) // this will call the constructor above, which will first call base. So the final chain is: base, constructor above, this constructor
{
// this method body is executed third (last if you used this constructor, e.g. new DerivedA() )
}
}
public class DerivedB : Base
{
public DerivedB(string name, int val) : base(val)
{
}
public DerivedB() : base(5) // this will call the base constructor, and then this constructor. The constructor above will not be used.
{
}
}
Try it online
Note that all classes have a parameterless constructor when no other constructor is defined, so the following two examples are equivalent:
public class BaseA
{
}
public class BaseB
{
public BaseB()
{
}
}
You'll note that SharpLab shows the compiler removed the empty constructor from BaseB() since it's superfluous.
Finally, a derived class without an explicitly defined constructor, will still call the base class constructor implicitly:
public class Base
{
public Base()
{
// this method body is executed first
Console.WriteLine("Base constructor");
}
}
public class Derived : Base
{
}
Try it online
So to summarise: unless your base class has a parameterless constructor, your derived class constructors have to either call a base constructor directly, or indirectly through another derived class constructor. Obviously you only need to call a single base constructor method, as with any other class instantiation. You don't need matching derived methods for each base method, so long as you can construct the base with the values you do have.

Passing delegate from class to class

I have two classes, first:
public class A
{
public delegate void Function();
public string name;
public Function function;
public A(string name, Function function)
{
this.name = name;
this.function = function;
}
}
And in second:
public class B
{
public delegate void Function();
List<A> ListA;
// somewhere in function
void F()
{
ListA[i].function();
}
// ---
public void AddA(string name, Function function)
{
ListA.Add(new A(name, function)); // error here
}
}
It throws these errors:
Error 2 Argument 2: cannot convert from 'App.B.Function' to 'App.A.Function'
Error 1 The best overloaded method match for 'App.A.A(string, App.A.Function)' has some invalid arguments
How to solve this?
You have declared Function delegate twice, one inside class A and one inside B.
So they're two different types, one called App.B.Function and the other called App.A.Function.
If you want to share this delegate with both the classes, just declare it once and out of the scope of the classes (i.e. in the assembly scope) e.g.:
public delegate void Function();
public class A
{
public string name;
...
}
public class B
{
List<A> ListA;
...
}
However, in the System namespace exist a certain number of generic delegates that can be used to represent various functions. Have a look at System.Action<> and System.Func<> types.
The reason it happen is that Function is declared twice, once in each clases

How to make a derived method, which takes different arguments than overriden function in C#?

I have a class, something like this:
class BaseClass
{
protected int X;
virtual void ChangeParameters(int NewX)
{
this.X = newX;
}
}
class DerivedClass1 : BaseClass
{
private int a;
private int b;
}
class DerivedClass2 : BaseClass
{
private int a;
}
Problem comes when I want to override ChangeParameters() function in derived classes, because each of them can have different number of parameters.
So here comes the question - how can I create a virtual function, which can vary in arguments number in derived classes?
PS. I don't want to use the params keyword, because I'd much prefer the user of the class to know exactly how many parameters he has to pass to the function.
You cannot. If it is an override, the signature must be an exact match. If you want different parameters, it doesn't sound like an override - after all... how would a caller call it, knowing just the base type? (substitution principal, etc)
BaseClass obj = GetSomeConcreteObject(); // actually a DerievedClass2
obj.ChangeParameters({what would go here?});
It sounds to me like these are just independent methods. You could have a virtual method that takes an array (with or without params), but then you need to accept that the caller can supply any size.
That's not really possible.
By definition, an override must maintain the same name and set of parameters (aka the signature) as the original method.
How is the runtime supposed to bind your "override" to a method call on the superclass if you are using different parameters? Imagine this were possible:
class A
{
virtual void Foo(int i) { Console.WriteLine(i); }
}
class B : A
{
override void Foo(int i, int j) { Console.WriteLine(i + j); }
}
// somewhere else
void DoSomething(A a)
{
a.Foo(1);
}
// later
DoSomething(new B()); // how will b.Foo get called inside DoSomething?
If you vary the parameters all you get is an overload.
Interesting trick could be done also using optional parameters, like this:
public class Base
{
public virtual void DoSomething(string param="Hello", string param1 = "Bye")
{
Console.WriteLine(string.Format("prm: {0}, prm1: {1}", param, param1));
}
}
public class Derived : Base
{
public override void DoSomething(string param="Ciao", string param1="Ciao")
{
Console.WriteLine(string.Format("prm: {0}, prm1: {1}", param, param1));
}
}
So you can use in code like:
Base a = new Derived();
a.DoSomething();
Output is:
prm: Hello, prm1: Bye
But you can now this:
Base a = new Derived();
a.DoSomething("Ciao");
and output like this:
prm: Ciao, prm1: Bye //!!

The type "MyProject.Bike" does not contain a constructor that takes '0' arguments C#

My problem is perhaps pretty simple, but I just started programming in C#.
My problem is, as listed above: "The type "MyProject.Bike" does not contain a constructor that takes '0' arguments".
I don't understand, because I don't try to make a call to this constructor with empty parentheses, and reading similar questions were all answered with "You have to much/not enough parameters...".
I just made this for learning, but I think inheritance is a pretty important concept, so I would like to be able to do that...
My code:
using System;
namespace MijnConsoleProject
{
public class Bike
{
protected int speed = 0;
public String name
{
get;
set;
}
public void speedUp(int increment)
{
this.speed += increment;
}
public void slowDown(int decrement)
{
this.speed -= decrement;
{
public override string ToString ()
{
return name + ": speed = " + speed;
}
public Bike(int initSpeed)
{
this.speed = initSpeed;
}
}
public class GearedBike : Bike
{
private int gear;
public GearedBike(string name)
{
this.name = name;
}
public bool changeGear(int gear)
{
if(gear < 8 && gear > 0)
{
this.gear = gear;
return true;
}
else
{
return false;
}
}
public override string ToString ()
{
return name + ": speed=" + speed + ", gear=" +gear;
}
public static void main(String[] args)
{
Bike fiets = new Bike(10);
Console.WriteLine("[Normal Bike:]");
Console.WriteLine("{0}\n", fiets);
GearedBike fiets2 = new GearedBike("Fiets");
Console.WriteLine("[Geared Bike:]");
Console.WriteLine("{0}\n", fiets2);
}
}
}
Your Bike class only has one constructor:
public Bike(int initSpeed)
{
this.speed = initSpeed;
}
This takes a single parameter.
When you derive a class that derived class' constructor calls a constructor from the base class.
In your GearedBike class' constructor you don't specify which constructor of Bike to call so the compiler assumes Bike(), which doesn't exist.
You probably want something like below, where we specify what base constructor to call, and pass in an appropriate value.
public GearedBike(string name)
: base(0)
{
this.name = name;
}
You might also want a GearedBike constructor where you can set the speed and name, like below:
public GearedBike(string name, int initSpeed)
: base(initSpeed)
{
this.name = name;
}
The constructor public GearedBike(string name) { ... } is a shorthand for public GearedBike(string name) : base() { ... }
You have to call the base-class constructor with an argument from your sub-class constructor or add a 0-param constructor to your base-class.
public GearedBike(string name) : base(42) {
// ...
}
The constructor are not inherited so in the class the extends bike you have to call the base class construcotr:
public GearedBike(string name):base(name)
{
this.name = name;
}
you don't need to do that if your base class has got a parameter less constructor
GearedBike does not call a constructor on the base class. If you do not explicitly call the constructor on the base class, the compiler will call the default constructor on the base class. The base class does not contain a default constructor; therefor you receive an error stating such.
C# compiler can generate a default constructor which may look like
public Bike()
{
}
This will only happen if the type doesn't have any user-defined constructors. In your case the class Bike has a constructor that takes an int:
public Bike(int initSpeed)
{
this.speed = initSpeed;
}
Thefore compiler doesn't generate you a default parameterless constructor.
Later in your code a type GearedBike use the parent type's constructor by calling :base() (which is added by the compiler) and this call fail as there is no parameterless constructor in the base class.

Assignment in constructor vs direct assignment

a basic question popped in my head this morning. Here it is:
Is there any difference between doing this:
public class MyClass
{
private object _myField = new object();
...
}
and doing the following:
public class MyClass
{
private object _myField;
public MyClass()
{
_myField = new object();
}
...
}
Yes, in the first, the field is initialized before the constructor call. In the second, the field is initialized during the constructor call.
Just to demonstrate casperOne's point...
using System;
public abstract class BaseClass
{
public BaseClass()
{
Console.WriteLine("Result for {0}: {1}", GetType(),
CalledByConstructor());
}
protected abstract string CalledByConstructor();
}
public class VariableInitializer : BaseClass
{
private string foo = "foo";
protected override string CalledByConstructor()
{
return foo;
}
}
public class ConstructorInitialization : BaseClass
{
private string foo;
public ConstructorInitialization()
{
foo = "foo";
}
protected override string CalledByConstructor()
{
return foo;
}
}
public class Test
{
static void Main()
{
new VariableInitializer();
new ConstructorInitialization();
}
}
Here the base class constructor calls an abstract method implemented in the child class - this means we get to see the state of the object before its constructor body starts executing. The results are here:
Result for VariableInitializer: foo
Result for ConstructorInitialization:
As you can see, the variable initializer has already executed - but in the case where initialization only occurs in the constructor body, foo still has its default value of null.
Calling virtual methods from constructors is generally a very bad idea for precisely this sort of reason.
To add to casperOne's answer, those are the only two possible approaches to initializing a readonly field. Per MSDN:
When a field declaration includes a
readonly modifier, assignments to the
fields introduced by the declaration
can only occur as part of the
declaration or in a constructor in the
same class.
In contrast, other fields (ie. not marked readonly) can be assigned elsewhere in the class, such as via a method call, although that could lead to needing to check its state before usage.

Categories

Resources