Suppose I have the following base and derived class in my C# program:
class BaseClass
{
public BaseClass() { }
public BaseClass(int someVal)
{
// do something here
}
}
class DerivedClass : BaseClass
{
public DerivedClass(string somethingNew)
: base()
{
// do something with the somethingNew varible
}
public DerivedClass(string somethingNew, int someVal)
: base(someVal)
{
// do **THE SAME THING** with the somethingNew varible as in first constructor
}
}
My question comes about in the final constructor - Ideally, what I'd like is to be able to do something along the lines of (although this won't compile):
public DerivedClass(string somethingNew, int someVal)
: base(someVal)
: this(somethingNew)
{
}
In other words, call both the base and the first constructor.
Is there any way to do this or do I just need to re-write the code inside each constructor in this case?
Thanks!!
Not to say this is the CORRECT answer (and I'd love to hear how others would recommend I do this), but what I ended up doing was creating a private setter method that either constructor can call along the following lines:
class DerivedClass : BaseClass
{
public DerivedClass(string somethingNew)
: base()
{
setVals(somethingNew);
}
public DerivedClass(string somethingNew, int someVal)
: base(someVal)
{
setVals(somethingNew);
}
private setVals(string somethingNew)
{
// do something with the somethingNew varible
}
}
It saved my issue of having to deal with repetitive code and seems to be the cleanest way to do this, but, as I said, I'd love to see what others recommend / if there's a way to do this better.
Thanks!!!
You could accomplish this using default, nullable parameters values in your constructors.
class BaseClass
{
public BaseClass(int? someVal = null)
{
if (someVal.HasValue)
{
//Do something here
}
}
}
class DerivedClass : BaseClass
{
public DerivedClass(string somethingNew, int? someVal = null)
: base(someVal) // Pass someVal into BaseClass
{
// Do something with SomethingNew
}
}
Which can then be called as:
var d = new DerivedClass("SomeValue");
var d2 = new DerivedClass("SomeOtherValue", 2);
I would design base class like this
class BaseClass
{
public BaseClass() { ... }
public BaseClass(int someVal) : this() { }
}
to ensure what ... code is executed always.
Related
I have the following example:
class A {
public A DoSomethingInternal() {
// Some work..
return this;
}
}
class B : A {
public void DoSomething() {
DoSomethingInternal().DoSomethingInternal().DoSomethingInternal();
}
}
DoSomethingInternal is a method that should not be called by the outside objects. It should only be accessible to A and the inheritors of A - so it sounds like it should be protected.
However, due to the fact that DoSomethingInternal is a "fluent" method, I cannot make it protected.
A solution that I see is:
class A {
public A DoSomethingInternal() {
// Some work..
return this;
}
}
class B : A {
public void DoSomething() {
((B)(((B)DoSomethingInternal()).DoSomethingInternal())).DoSomethingInternal();
}
}
but I find it very inelegant to require derived classes to do these casts.
You can "tell" base class about derived class as a generic type argument.
public abstract class A<T> where T : A<T>
{
protected T DoSomethingInternal()
{
// Do something
return (T)this;
}
}
public class B : A<B>
{
public void DoSomething()
{
// Do something
this.DoSomethingInternal().DoSomethingInternal();
}
}
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.
With the abstract following class:
public abstract class A
{
public static string MyMethod()
{
return "a";
}
}
Why can't I built this derived abstract class:
public class B<T> where T : A
{
public void AnotherMethod()
{
var S1 = base.MyMethod(); // not allowed
var S2 = T.MyMethod(); // not allowed
}
}
I don't understand why since MyMethod will be available in type T.
There are two misconceptions in your question that collectively prevent both your attempts from working.
First your B class is not in any way derived from the A class, you have only said that it takes a generic parameter that must inherit from A.
Second as the user #recursive pointed out, static methods do not participate in inheritance so MyMethod would only ever be available as A.MyMethod()
You can make at least your first attempt work if you remove the static modifier and make B inherit from A instead of using generics.
// Removed the static modifier
public abstract class A
{
public string MyMethod()
{
return "a";
}
}
// Made B inherit directly from A
public class B : A
{
public void AnotherMethod()
{
var S1 = base.MyMethod(); //base technically isn't required
}
}
Aside from the fact that A.MyMethod is static, which clearly will not work since anything static does not take part in inheritance, even if you made it not static it still will not work. For example, this will not work either:
public abstract class A {
public string MyMethod() {
return "a";
}
}
public class B<T> where T : A {
public void AnotherMethod() {
var S1 = base.MyMethod(); // Line 1
var S2 = T.MyMethod(); // Line 2
}
}
Why?
You are saying where T : A which means that type T has to be a derived type from A. Your class B<T is not a derived type of A so Line 1 will not work.
But why is Line 2 not working?
T is a type and if T is inheriting A, then objects of type T will be able to do that. If you changed it like this, then it will work:
public abstract class A {
public string MyMethod() {
return "a";
}
}
public class B<T> where T : A {
public void AnotherMethod(T t) {
t.MyMethod();
}
}
public class C : A {
}
public class BClosed : B<C> {
public void Foo(C c) {
c.MyMethod();
this.AnotherMethod(c);
}
}
In the above code, C derives A which was your restriction. Then BClosed closes the generic type saying T is C so now you can call MyMethod of A and AnotherMethod of your generic.
Also, when you have a generic class you should use the generic type otherwise I do not see the use. So this is useless since it has no generic code:
public class B<T> where T : A {
public void AnotherMethod() {
}
}
Is it possible to overload constructors in C# so that the program chooses to use one constructor if the argument is of a derived class and a different if it is the base class. For instance
class BaseClass {...}
class DerivedClass : BaseClass {...}
class foo
{
public foo(DerivedClass bar)
{
//do one thing
}
public foo(BaseClass bar)
{
//do another
}
}
That is, I want the program to pick the correct constructor based on the object type.
I agree with everyone else that this feels like a code smell, but if you actually compile your code and run it, you'll find that it already works the way you want it to. For instance, this does exactly what you want it to do, for better or for worse.
class Program
{
static void Main(string[] args)
{
var b = new BaseClass();
var d = new DerivedClass();
var f = new foo(d);
//prints Derived Constructor
var e = new foo(b);
//prints Base Constructor
}
}
public class BaseClass {
public BaseClass()
{
}
}
public class DerivedClass : BaseClass
{
public DerivedClass()
{
}
}
class foo
{
public foo(DerivedClass bar)
{
//do one thing
Console.WriteLine("Derived Constructor");
}
public foo(BaseClass bar)
{
Console.WriteLine("Base Constructor");
}
}
I think the best answer for your question is a bit indirect, but the best proximate answer to your question would be along the lines of this:
Edit: correcting incorrect is syntax usage and making it more specific
public foo(BaseClass foobar) {
if (foobar?.GetType() == typeof(BaseClass)) {
//do something
}
else { // do something different }
}
That being said, I don't think that this is necessarily the optimum way to structure your code; making decisions based on object type can be a signal that it's time to leverage polymorphism via abstract/virtual classes and methods. You're better off IMO doing something like this:
public BaseClass {
public virtual void DoSomething() {...}
}
public DerivedClass : BaseClass {
public override void DoSomething() {...}
}
public foo(BaseClass foobar) {
foobar.DoSomething();
}
If you cast your object in your BaseClass the good constructor will be called.
Like so:
void Main()
{
var object2 = new DerivedClass();
var temp = new Allo((BaseClass)object2);
}
public class Allo
{
public Allo(BaseClass value)
{
Console.WriteLine("baseclass");
}
public Allo(DerivedClass value)
{
Console.WriteLine("derivedclass");
}
}
public class BaseClass
{
}
public class DerivedClass : BaseClass
{
}
Output:
baseclass
When I wrote a simple version of the program shown above, it did correctly choose the derived class-method when the constructor was called with the derived class.
[I was getting strange behavior when I tested as part of my larger project... but I realize now those were due to other errors in my code - a reminder to myself to actually test things - this is the first time in four years I've done any programming so I am forgetting the basics...].
I had a question on C# generics. I wish to store a generic type variable in my abstract class without declaring that type outside the class.
Below is the code sample. Please note that I do not wish to make the Param classes exposed outside the Calc class.
Thanks in advance.
- Dutta.
abstract class Base { }
abstract class Calc<T> where T : Base
{
protected Param Member; /* how can this be a made a generic declaration
* WITHOUT declaring this class like,
* class Calc<T, P>
* where T : Base
* where P : Param */
protected Calc(Param p)
{
this.Member = p;
}
protected abstract class Param { }
}
class MyBase : Base { }
class MyCalc : Calc<MyBase>
{
public MyCalc() : base(new MyParam()) { }
public void doSomething()
{
base.Member.A++; // fails on compilation
}
private class MyParam : Calc<MyBase>.Param
{
public int A;
public MyParam() { this.A = 0; }
}
}
You just need to cast it to the new type, because no matter what, the variable Member was declared as Param and it will always be accessed as Param:
((MyParam)base.Member).A++;
Secondly, you can fix up your MyParam class by changing from this:
MyParam : Calc<MyBase>.Param
To this:
MyParam : Param
Because Param is already Calc<MyBase> through generics and inheritance.
Thraka's answer is correct: if you don't want to use generics you need to cast. Just to add to it, in case what you're really trying to do looks something like this. Here's a set of classes that you can expose from your library, which will not be extensible by clients (unless they're running with full trust and can use reflection etc.!!) but which can be used in a type-safe way.
public abstract class SupportedPaymentMethod
{
protected internal SupportedPaymentMethod() { }
}
public sealed class Check : SupportedPaymentMethod
{
public int CheckNumber { get; private set; }
public Check(int checkNumber)
: base()
{
CheckNumber = checkNumber;
}
}
public sealed class CreditCard : SupportedPaymentMethod
{
public CreditCard()
: base()
{ }
}
public abstract class Payment<T>
where T : SupportedPaymentMethod
{
public T Method { get; private set; }
protected internal Payment(T method)
{
Method = method;
}
}
public sealed CheckPayment : Payment<Check>
{
public CheckPayment(Check check)
: base(check)
{ }
}
public sealed CreditCardPayment : Payment<CreditCard>
{
public CreditCardPayment(CreditCard creditCard)
: base(creditCard)
{ }
}
Clients (i.e. code outside of your class library's assembly) will be able to instantiate a CheckPayment or a CreditCardPayment, but they will not be able to create a new class deriving from Payment<T>. So, it will not be possible for clients to create a CheatingPaymentMethod : Payment<Cheating>, for example. :)
Calls like your intended call to base.Member.A++ will now work:
var checkPayment = new CheckPayment(new Check(123456));
var checkNumber = checkPayment.Method.CheckNumber; // Success! :)