abstract class CAbstract
{
private string mParam1;
public CAbstract(string param1)
{
mParam1 = param1;
}
}
class CBase : CAbstract
{
}
For the class CBase, it should be initialized by providing the parameter, so how to disable the parameterless constructor for CBase class?
If you define a parameterized constructor in CBase, there is no default constructor. You do not need to do anything special.
If your intention is for all derived classes of CAbstract to implement a parameterized constructor, that is not something you can (cleanly) accomplish. The derived types have freedom to provide their own members, including constructor overloads.
The only thing required of them is that if CAbstract only exposes a parameterized constructor, the constructors of derived types must invoke it directly.
class CDerived : CAbstract
{
public CDerived() : base("some default argument") { }
public CDerived(string arg) : base(arg) { }
}
To disable default constructor you need to provide non-default constructor.
The code that you pasted is not compilable. To make it compilable you could do something like this:
class CBase : CAbstract
{
public CBase(string param1)
: base(param1)
{
}
}
Please correct me if I am wrong, but I think I achieved that goal with this code:
//only for forbiding the calls of constructors without parameters on derived classes
public class UnconstructableWithoutArguments
{
private UnconstructableWithoutArguments()
{
}
public UnconstructableWithoutArguments(params object[] list)
{
}
}
Related
I have written a simple generic class in C#.
class Foo<T>
{
public object O{get;set;}
public Foo(object o)
{
O=o;
}
}
and another class inheriting from it
class Bar:Foo<object>
{
public Foo(object o):base(o)
{ }
}
My question is whether I can avoid writing that constructor in Bar class, because it does nothing special at all. PS: the parameter in constructor is necessary.
No, you can't. There's no inheritance of constructors. The constructor in Bar does do something: it provides an argument to the base constructor, using its own parameter for that argument. There's no way of doing that automatically.
The only constructor the compiler will supply for you automatically is one of equivalent to:
public Bar() : base()
{
}
for a concrete class, or for an abstract class:
protected Bar() : base()
{
}
... and that's only provided if you don't supply any other constructors explicitly.
I am trying to learn C#. The below data is from a Microsoft C# help website.
I don't understand this statement, "If a base class does not offer a default constructor, the derived class must make an explicit call to a base constructor by using base."
I thought that if there is no default constructor for a class, C# will automatically assign default values to int, char or whatever is declared in a class. If a base class does not have a constructor and it has a child class, does the rule mentioned in the last sentence not apply? Please clarify.
In a derived class, if a base-class constructor is not called explicitly by using the base keyword, the default constructor, if there is one, is called implicitly. This means that the following constructor declarations are effectively the same:
C#
public Manager(int initialdata)
{
//Add further instructions here.
}
C#
public Manager(int initialdata)
: base()
{
//Add further instructions here.
}
If a base class does not offer a default constructor, the derived class must make an explicit call to a base constructor by using base.
If you do not define a constructor for a class:
public class DemoClass
{
public void SomeFunction() { }
}
C# will add a default (parameterless) constructor for you. In this case; nothing special needs to be done with derived classes, as they will use the provided default constructor. Of course, you can always define your own default (parameterless) constructor:
public class DemoClass
{
public void DemoClass() { }
public void SomeFunction() { }
}
Which still doesn't require anything special for derived classes, since they can still use it. If however, you define a parameterized constructor, without defining a default:
public class DemoClass
{
public void DemoClass(string argument) { }
public void SomeFunction() { }
}
Now there is no default (parameterless) constructor for derived classes to use; and you need to say which constructor to use with base:
public class DerivedClass : DemoClass
{
public DerivedClass() : base(String.Empty) { }
}
For reasons out of the scope of the question, I'm needing to dynamically create an instance of a child class that inherits from a base class, calling a constructor that doesn't exist with an argument passed to the base class constructor
Using example below: should create an instance of ExampleClass sending value to argument1 of BaseClass.
class BaseClass
{
public BaseClass()
{
}
public BaseClass(string argument1)
{
//...
}
}
class ExampleClass : BaseClass
{
public ExampleClass()
{
}
}
EDIT: I made another topic where I explain the source or my problem:
Entity Framework DbContext dynamic instatiation with custom Connection String
If I understand it correct you can't modify ExampleClass but need to create an instance of it that uses a different constructor for the base class?
I belive there is not build in way in the framework to achive it, even with reflection.
So your goal should be to bypass the framework and use MSIL
However, this topic I found on SO looks promissing.
Dynamically create type and call constructor of base-class
Do you want to call the base class' constructor?
public ChildClass(string arg1) : base(arg1)
{
//above will invoke base constructor that takes a string argument
}
The only way I can see to do this is to add a ParentClass constructor. I doesn't have to do anything, so I don't see why you can't add it:
public ParentClass(string argument1) : BaseClass(argument1)
{
}
Try this:
class ExampleClass : BaseClass
{
public ExampleClass()
: base(Properties.Settings.Default.MyArgument)
{
}
}
You can use Properties.Settings.Default.MyArgument in order to pass in the value of the argument you want use in the base class constructor without modifying the source code everytime the argument's value needs to be changed (just add it into the projects's Settings, application scoped).
If you can't add a non-default constructor to your ChildClass, then no you can't create an instance of ChildClass calling a base class constructors. Constructors are not inherited. What you need to then is to refactor your base class so that there is way to set the argument not using a constructor. For example see below:
class BaseClass
{
public BaseClass()
{
}
public BaseClass(string argument1)
{
Init(argument1);
}
public void Init(string argument1)
{
//...
}
}
class ExampleClass : BaseClass
{
public ExampleClass()
{
}
}
Then you can create an instance of your ExampleClass and call the Init method to initialize it:
ExampleClass e = (ExampleClass)Activator.CreateInstance.... // or whatever
e.Init(arugment);
This won't compile:
namespace Constructor0Args
{
class Base
{
public Base(int x)
{
}
}
class Derived : Base
{
}
class Program
{
static void Main(string[] args)
{
}
}
}
Instead, I get the following error:
'Constructor0Args.Base' does not contain a constructor that takes 0 arguments
Why is that? Is it necessary for a base class to have a constructor that takes 0 arguments?
It isn't - the problem is that it needs to call some base constructor, in order to initialise the base type, and the default is to call base(). You can tweak that by specifying the specific constructor (and arguments) yourself in the derived-types constructor:
class Derived : Base
{
public Derived() : base(123) {}
}
For parameters to base (or alternatively, this) constructors, you can use:
parameters to the current constructor
literals / constants
static method calls (also involving the above)
For example, the following is also valid, using all three bullets above:
class Derived : Base
{
public Derived(string s) : base(int.Parse(s, NumberStyles.Any)) {}
}
When you derive a class from another, the base class will be called before the derived classes constructor. When you don't explicitly call a constructor you are essentially writing
class Derived : Base
{
public Derived() : base()
{
}
}
Since the Base class doesn't have a 0 argument constructor, this is invalid.
If you don't explicitly define a constructor for a class, a default constructor is automatically defined, which looks like this:
public Derived() : base()
{
}
You need to specify the constructor on the base class as well as which arguments to pass to it:
public Derived() : base(1)
{
}
This is becase when the child class is instantiated, it will also instantiate the base class. By default, it will try to find a arg less constructor. This is work with this code:
class Base
{
public Base(int x) { }
}
class Derived : Base
{
public Derived(int x)
: base(x)
{
}
}
public abstract class Request
{
public class Parameters
{
//Threre are no members here
//But there should be in inherited classes
}
public Request()
{
parameters = new Parameters();
}
public Parameters parameters;
}
Two questions:
How do I make it so I can add stuff to the constructor but the original constructor will still be executed?
How do I make it so the subclasses can add members to the Parameters class?
If you're doing what I think you are you would have to change your constructor slightly:
public Request(Parameters parameters) {
this.Parameters = parameters;
}
and then you can do this:
public class SpecificRequest : Request {
public class SpecificRequestParameters : Request.Parameters {
}
public SpecificRequest() : base(new SpecificRequestParameters()) {
//More stuff here
}
}
What's the specific problem that you're trying to address? What you're doing here seems fairly awkward and overly complicated.
Why do you embed the Parameters class inside the Request class? Instead, let Request have an instance of parameters and just declare the class somewhere else.
Answer for your question 1:
Inherit from Request and the original request constructor will always be called.
Question 2:
Subclasses cannot add members to parameter classes (except with reflection, but you dont want to walk that path). Best you can do is inherit from parameter and have the InheritedRequest use the InheritedParameter class. Note that in that case you cannot override the properties and properties. You will have to have an additional property in InheritedRequest called AdditionalParameters of type InheritedParameters.
Constructors can be chained with the syntax
ctor() : this()
or
ctor() : base()
in there you can pass parameters along etc.
Make the Parameters field generic
abstract class Request<T> where T : Parameters {
T Parameters;
}
class Specialized : Request<SpecialParameters> {
}
where SpecialParameters inherits from Parameters.