This question already has answers here:
Calling this and base constructor?
(1 answer)
How do I call both this and base constructor
(2 answers)
Can I call both this and base overloads in a constructor?
(1 answer)
Closed 3 years ago.
I know how to call another constructor for a constructor from the same class or the base class, but how can I do both at once? Here is an example of what I am looking to achieve, noting that in a real case we might want to do something more complex than just set a property:
public class BaseClass
{
public BaseClass(object param)
{
// base constructor
}
}
public class DerivedClass
{
DateTime Date { get; private set; }
public DerivedClass()
{
Date = GenerateDate();
}
public DerivedClass(object param) : base(param)
{
// How do I make it call DerivedClass() ?
}
}
This code actually compiles in Sharp Lab. Not that I had to fix a few secondary things.
using System;
public class BaseClass
{
public BaseClass(object param)
{
// base constructor
}
}
public class DerivedClass : BaseClass
{
public DateTime Date { get; private set; }
public DerivedClass() : this(new object()) { }
public DerivedClass(object param) : base(param)
{
//Do Date = GenerateDate(); here
//Had to cut your pseudo code, as it broke compilation
}
}
You had it the wrong way around: You need DerivedClass() to call DerivedClass(object param). With multiple Constructors, the one you actually code out is always the one with the most arguments. All other Constructors are just there to chain towards it, giving a default value each step.
Related
Say you have a parent class with lots of subclasses. If the constructor of the parent gets a new parameter you would have to change all the children constructors, too. Is there a way to inherit the parent constructor without naming all the parameters?
Code that I want to write, but gives the error 'There is no argument given for the formal parameter...':
public abstract class A
{
public A(someType somePar)
{
}
}
public class B : A
{
}
Annoying solution:
public abstract class A
{
public A(someType somePar)
{
}
}
public class B : A
{
//If there is a new parameter, this would need to change
B(someType somePar) : base(somePar)
{
}
}
Sorry if there is an obvious solution to this, I'm writing for the first time with C#
This question already has an answer here:
Generic Type in constructor
(1 answer)
Closed 2 years ago.
I have a generic class. The constructor needs to accept an argument that is another instance of the same class. The problem is that the other instance can have a different generics type.
Looks like C# allows me to have a method with it's own generics type, but this doesn't appear allowed for the constructor.
public class MyClass<T>
{
public MyClass<T2>(MyClass<T2> parent = null)
{
}
// ... Additional stuff
}
The code above tells me T2 is undefined. It doesn't accept it as a method type.
One approach would be to add a second generic type to my class. But this is awkward and, in many cases, the argument will be null and there is not type.
Does anyone see a simple way around this?
Generic constructors aren't allowed. However, you can use a generic factory method instead.
public class MyClass<T>
{
public int Id { get; private set; }
public int? ParentId { get; private set; }
public static MyClass<T> Create(int id)
{
return Create<object>(id, null);
}
public static MyClass<T> Create<T2>(int id, MyClass<T2> parent = null)
{
var current = new MyClass<T>();
current.Id = id;
current.ParentId = parent?.Id;
return current;
}
private MyClass()
{
}
// ... Additional stuff
}
Sample use:
var intClass = MyClass<int>.Create(55);
var charClass = MyClass<char>.Create(234, intClass);
// charClass.ParentId is 55
This is only possible if you do not need to access any generic members of parent outside the factory method. If you do, you'd be better off abstracting it through a non-generic interface or base class.
You are correct. Generic constructors aren't supported.
You could probably try the following:
Create a lower level common interface
public interface IMyClass {
//...some common stuff
IMyClass Parent { get; set; }
}
And use that as the common link between the types
public class MyClass<T> : IMyClass {
public MyClass(IMyClass parent = null) {
Parent = parent;
}
public IMyClass Parent { get; set; }
// ... Additional stuff
}
This question already has answers here:
Keyword 'this' (Me) is not available calling the base constructor
(4 answers)
Closed 9 years ago.
I have the following initialization of a constructor:
public partial class WizardPage1 : WizardPage
{
public WizardPage1()
: base(0, getLocalizedString(this.GetType(), "PageTitle"))
{
}
}
where
public static string getLocalizedString(Type type, string strResID)
{
}
but this.GetType() part causes the following error:
error CS0027: Keyword 'this' is not available in the current context
Any idea how to resolve it?
The 'this' keyword refers to the current instance of the class. In the constructor, you don't have access to the instance because you are about to create one... So try below:
public partial class WizardPage1 : WizardPage
{
public WizardPage1()
: base(0, getLocalizedString(typeof(WizardPage1), "PageTitle"))
{
}
}
The this keyword refers to the current instance of a class, however as you are calling this within the constructor, you don't yet have an instance to refer to (as it is being constructed).
Perhaps an alternate solution would be to have a property in your base class that you can override in the child class. E.g.
public class WizardPage
{
public virtual string PageTitle { get; }
...
}
public class WizardPage1 : WizardPage
{
public override string PageTitle
{
get
{
return getLocalizedString(this.GetType(), "PageTitle");
}
}
}
The key thing here is that you are calling GetType() when you already have an instance of the object.
#Damith is correct on why this doesn't work but one way to deal with this simpler could be to (ignoring implementation specifics):
public abstract class WizardPage
{
// Replace or override existing constructor with this
public WizardPage(int unknownInt, Type currentType, string str)
{
if (currentType == null)
currentType = System.Reflection.MethodBase()
.GetCurrentMethod().GetType();
var localString = getLocalizedString(currentType, str);
// Existing logic here
}
}
And change your child class to:
public partial class WizardPage1 : WizardPage
{
public WizardPage1()
: base(0, this.GetType(), "PageTitle")
{
}
}
Unfortunately, this approach require adding a layer of abstraction if you don't have access to the code of the base class.
This question already has answers here:
How to dynamically create generic C# object using reflection? [duplicate]
(5 answers)
Closed 9 years ago.
[NOTE: I don't believe this question is a duplicate of the one linked above, as I explain in the UPDATE below.]
Is there any way to define/instantiate a generic class using reflection?
So I have a bunch of classes, each of which owns an instance of a generic class that shares the type of its owner:
public class GenericClass<T>
{
T Owner { get; set; }
public GenericClass(T owner) { Owner = owner; }
}
public class MyClass
{
private GenericClass<MyClass> myGenericObject;
public MyClass() { myGenericObject = new GenericClass<MyClass>(this); }
}
This works, but of course I have to explicitly specify "MyClass" as the argument in the GenericClass definition. I'd like to be able to do something like this:
private GenericClass<typeof(this)> myGenericObject; // Error: invalid token
Is there anyway to dynamically specify the type of the generic object at compile time, based on the containing class?
UPDATE: After reading the answers from these questions, I learned that I could instantiate a local variable like so:
var myGenericObject = Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(this.GetType()));
but, of course, the this keyword is only available inside a method (so, for example, I could put this line of code in the constructor of MyClass). But I cannot use this approach to define an instance variable (i.e., myGenericObject, in the code above). Is there any way to specify a generic instance variable dynamically?
Regarding your update, you can pass any Type to MakeGenericType. For example, the following also works:
var myObject = new MyClass();
var myGenericObject = Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(typeof(MyClass)), myObject);
Console.WriteLine(myGenericObject.GetType());
Outputs:
ConsoleApplication1.GenericClass`1[ConsoleApplication1.MyClass]
myObject.GetType() also does the same thing:
var myGenericObject = Activator.CreateInstance(typeof(GenericClass<>).MakeGenericType(myObject.GetType()), myObject);
Not sure if that is what are you looking for but can try with inheritance:
public class GenericClass<T>
{
T Owner { get; set; }
public GenericClass(T owner) { Owner = owner; }
}
public abstract class MyClassBase<T> where T : MyClassBase<T>
{
protected GenericClass<T> MyGenericObject { get; private set; }
protected MyClassBase() { MyGenericObject = new GenericClass<T>((T)this); }
}
public class MyClass1 : MyClassBase<MyClass1>
{
public MyClass1() { }
}
public class MyClass2 : MyClassBase<MyClass2>
{
public MyClass2() { }
}
There is static built in construct for that:
Activator.CreateInstance()
Look at the overloads.
UPDATE
public Type FakeType { get; private set; }
public T CreateInstance<T>() where T : SomeEntityBase
{
return (T) Activator.CreateInstance(FakeType);
}
This question already has answers here:
What's a good threadsafe singleton generic template pattern in C#
(23 answers)
Closed 9 years ago.
I am trying to create a generic singleton base class like
public class SingletonBase<T> where T : class, new()
{
private static object lockingObject = new object();
private static T singleTonObject;
protected SingletonBase()
{
}
public static T Instance
{
get
{
return InstanceCreation();
}
}
public static T InstanceCreation()
{
if(singleTonObject == null)
{
lock (lockingObject)
{
if(singleTonObject == null)
{
singleTonObject = new T();
}
}
}
return singleTonObject;
}
}
But I have to make constructor as public in derived one.
public class Test : SingletonBase<Test>
{
public void A()
{
}
private Test()
: base()
{ }
}
Compilation Error:
'Test' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test'
How can I achieve this?
The problem is your generic constraint where T : class, new(). The new() constraint requires a public, parameterless constructor on T. There is no way around this; you need to provide such a constructor in Permission Controller.
I would avoid this kind of recursive generic pattern. Read this this blog post for a detailed explanation of the pattern and reasons not to use it.
As far as I can tell, you don't need to have any sub-classes of SingletonBase<T>. I can't see anything that a subclass of SingletonBase<T> would be able to add to your code. I would simply rewrite it as
public static class Singleton<T> where T : class, new()
{
...
}
You can then use it as
var test = Singleton<Test>.Instance;
If you want to be able to use Test as a singleton, create it as
public class Test
{
public static T Instance
{
get { return Singleton.Instance<Test>; }
}
}