Though many questions on this topic exist, I am unable to find (yet) a satisfying solution:
Is it possible (and if yes, how?) to access a derived class from the base virtual method?
Let's imagine I have the following classes:
public class parent_class
{
public virtual string common_method () {
dynamic child = /* something to access the derived class */ ;
if (child == null)
return typeof(parent_class).FullName;
else
return child.GetType().FullName;
}
}
public class child_class1 : parent_class {}
public class child_class2 : parent_class {}
public class child_class3 : parent_class {}
Is it possible to execute the following code (and getting the correct result)?
parent_class p = new parent_class();
child_class1 c1 = new child_class1();
child_class2 c2 = new child_class2();
child_class3 c3 = new child_class3();
System.Console.WriteLine(p.common_method()); // result: 'parent_class'
System.Console.WriteLine(c1.common_method()); // result: 'child_class1'
System.Console.WriteLine(c2.common_method()); // result: 'child_class2'
System.Console.WriteLine(c3.common_method()); // result: 'child_class3'
EDIT: After reading the comments and replies I have to add the following points:
I have about 300 different "child classes", so overriding is not an option
I do not want to print the derived class' name - It was just an example
#Siamak Ferdos: I tried the this-keyword, but it somehow did not work as I intended.
Yes you can do it by 'this' keyword simply:
public class parent_class
{
public virtual string common_method()
{
//dynamic child = /* something to access the derived class */ ;
if (this.GetType() == typeof(parent_class))
return typeof(parent_class).FullName;
else
return this.GetType().FullName;
}
}
public class child_class1 : parent_class { }
public class child_class2 : parent_class { }
public class child_class3 : parent_class { }
If I understand your question correctly, you want to print the classes full name via a common base class method. At runtime, the actual instantiated type name is what GetType().FullName will produce, not the type of the base class.
This can be tested with a simple example:
void Main()
{
var parent = new Parent();
var child = new Child();
Console.WriteLine(parent.GetName());
Console.WriteLine(child.GetName());
}
public class Parent
{
public string GetName()
{
return this.GetType().FullName;
}
}
public class Child : Parent
{
}
Yields:
UserQuery+Parent
UserQuery+Child
Where UserQuery is the defined namespace.
There is no need for the method to be virtual or overriden in the derived class for this to work.
Related
I have the following classes
public abstract class BaseViewPresenter { }
public abstract class BaseView<T> : UserControl
where T : BaseViewPresenter { }
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter> { }
I have a method that looks like this (simplified)
public BaseView<BaseViewPresenter> Resolve(BaseViewPresenter model)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
// Correctly creates BaseView object
var control = Activator.CreateInstance(viewType);
// Fails to cast as BaseView<BaseViewPresenter> so returns null
return control as BaseView<BaseViewPresenter>;
}
When I call this using an instances of LoginPresenter
var login = new LoginPresenter();
var ctl = Resolve(login);
The line Activator.CreateInstance(viewType) correctly resolves into a new instances of my LoginView, however control as BaseView<BaseViewPresenter> can't do the cast correctly so returns null.
Is there a way to correctly cast the control into BaseView<BaseViewPresenter> without using specific type generics?
Since LoginView inherits from BaseView<LoginPresenter>, and LoginPresenter inherits from BaseViewPresenter, I would assume there's a way to convert LoginView to BaseView<BaseViewPresenter>.
I am stuck with using .Net 3.5
This is a very frequently asked question. Let's rename your types:
abstract class Fruit { } // was BaseViewPresenter
abstract class FruitBowl<T> where T : Fruit // was BaseView
class Apple : Fruit { } // was LoginPresenter
class BowlOfApples : FruitBowl<Apple> { } // was LoginView
Your question now is:
I have a BowlOfApples, which inherits from FruitBowl<Apple>. Why can I not use it as a FruitBowl<Fruit>? An apple is a fruit, so a bowl of apples is a bowl of fruit.
No, it isn't. You can put a banana in a bowl of fruit, but you can't put a banana in a bowl of apples, and therefore a bowl of apples is not a bowl of fruit. (And by similar argument, a bowl of fruit is not a bowl of apples either.) Since the operations you can legally perform on the two types are different, they cannot be compatible.
Here is a photo of StackOverflow legend Jon Skeet demonstrating this fact:
The feature you want is called generic contravariance, and it is supported only on interfaces and delegate types when the compiler can prove that the variance is safe, and when the varying type is a reference type. For example, you can use an IEnumerable<Apple> in a context where IEnumerable<Fruit> is needed because the compiler can verify that there is no way that you can put a Banana into a sequence of fruit.
Do a search on "C# covariance and contravariance" on this site or on the web and you'll find many more details about how this feature works. In particular, my series of articles on how we designed and implemented this feature in C# 4 starts here: http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx
I accepted Eric's answer since it provides a great explanation of why what I wanted wasn't possible, but I also thought I'd share my solution in case anyone else runs into this same problem.
I removed the generic type parameter from my original BaseView class, and created a 2nd version of the BaseView class that included the generic type parameter and specifics for it.
The first version is used by my .Resolve() method or other code that doesn't care about the specific types, and the second version is used by any code that does care, such as the implentation of a BaseView
Here's an example of how my code ended up looking
// base classes
public abstract class BaseViewPresenter { }
public abstract class BaseView : UserControl
{
public BaseViewPresenter Presenter { get; set; }
}
public abstract class BaseView<T> : BaseView
where T : BaseViewPresenter
{
public new T Presenter
{
get { return base.Presenter as T; }
set { base.Presenter = value; }
}
}
// specific classes
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter>
{
// Can now call things like Presenter.LoginPresenterMethod()
}
// updated .Resolve method used for obtaining UI object
public BaseView Resolve(BaseViewPresenter presenter)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
BaseView view = Activator.CreateInstance(viewType) as BaseView;
view.Presenter = presenter;
return view;
}
You're expecting to treat the type as being covariant with respect to the generic argument. Classes can never be covariant; you'd need to use an interface rather than (or in addition to) an abstract class to make it covariant with respect to T. You'd also need to be using C# 4.0.
My usual solution to this problem is to create an intermediary class that has access to the type-parametric class's methods through delegates. Fields can also be accessed through getters/setters.
The general pattern goes:
public abstract class Super {}
public abstract class MyAbstractType<T> where T : Super {
public MyGeneralType AsGeneralType() {
return MyGeneralType.Create(this);
}
// Depending on the context, an implicit cast operator might make things
// look nicer, though it might be too subtle to some tastes.
public static implicit operator MyGeneralType(MyAbstractType<T> t) {
return MyGeneralType.Create(t);
}
public int field;
public void MyMethod1() {}
public void MyMethod2(int argument) {}
public abstract bool MyMethod3(string argument);
}
public delegate T Getter<T>();
public delegate void Setter<T>(T value);
public delegate void MyMethod1Del();
public delegate void MyMethod2Del(int argument);
public delegate bool MyMethod3Del(string argument);
public class MyGeneralType {
public Getter<int> FieldGetter;
public Setter<int> FieldSetter;
public MyMethod1Del MyMethod1;
public MyMethod2Del MyMethod2;
public MyMethod3Del MyMethod3;
public static MyGeneralType Create<T>(MyAbstractType<T> t) where T : Super {
var g = new MyGeneralType();
g.FieldGetter = delegate { return t.field; };
g.FieldSetter = value => { t.field = value; };
g.MyMethod1 = t.MyMethod1;
g.MyMethod2 = t.MyMethod2;
g.MyMethod3 = t.MyMethod3;
return g;
}
public int field {
get { return FieldGetter(); }
set { FieldSetter(value); }
}
}
The above exemplifies getting all the methods and fields but normally I only need a few of them. This is a general solution to the problem and one could feasibly write a tool to generate these intermediary classes automatically, which I might at some point.
Try it here: https://dotnetfiddle.net/tLkmgR
Note that this is enough for all my cases, but you can be extra hacky with this:
public abstract class MyAbstractType<T> where T : Super {
// ... Same everything else ...
// data fields must become abstract getters/setters, unfortunate
public abstract int field {
get;
set;
}
public static implicit operator MyAbstractType<Super>(MyAbstractType<T> t) {
return MyGeneralType.Create(t);
}
}
public class MyGeneralType : MyAbstractType<Super> {
// ... same constructors and setter/getter
// fields but only keep method fields
// that contain the method references for
// implementations of abstract classes,
// and rename them not to clash with the
// actual method names ...
public MyMethod3Del myMethod3Ref;
// Implement abstract methods by calling the corresponding
// method references.
public override bool MyMethod3(string argument) {
return myMethod3Ref(argument);
}
// Same getters/setters but with override keyword
public override int field {
get { return FieldGetter(); }
set { FieldSetter(value); }
}
}
And there you go, now you can literally cast a MyAbstractType<Sub> where Sub : Super to a MyAbstractType<Super>, although it's no longer the same object anymore, but it does retain the same methods and data, it's sort of a complex pointer.
public class Sub : Super {}
public class MySubType : MyAbstractType<Sub> {
public int _field;
public override int field {
get { return _field; }
set { _field = value; }
}
public override bool MyMethod3(string argument) {
Console.WriteLine("hello " + argument);
return argument == "world";
}
}
public class MainClass {
public static void Main() {
MyAbstractType<Sub> sub = new MyAbstractType<Sub>();
MyAbstractType<Super> super = sub;
super.MyMethod3("hello"); // calls sub.MyMethod3();
super.field = 10; // sets sub.field
}
}
This isn't as good in my opinion, the other version of MyGeneralType is a more straighforward layer over the concrete types, plus it doesn't require rewriting the data fields, but it does actually answer the question, technically. Try it here: https://dotnetfiddle.net/S3r3ke
Example
Using these abstract classes:
public abstract class Animal {
public string name;
public Animal(string name) {
this.name = name;
}
public abstract string Sound();
}
public abstract class AnimalHouse<T> where T : Animal {
List<T> animals;
public AnimalHouse(T[] animals) {
this.animals = animals.ToList();
}
public static implicit operator GeneralAnimalHouse(AnimalHouse<T> house) {
return GeneralAnimalHouse.Create(house);
}
public List<string> HouseSounds() {
return animals.Select(animal => animal.Sound()).ToList();
}
}
We make this "general" variant:
public delegate List<string> HouseSoundsDel();
public class GeneralAnimalHouse {
public HouseSoundsDel HouseSounds;
public static GeneralAnimalHouse Create<T>(AnimalHouse<T> house) where T : Animal {
var general = new GeneralAnimalHouse();
general.HouseSounds = house.HouseSounds;
return general;
}
}
And finally with these inheritors:
public class Dog : Animal {
public Dog(string name) : base(name) {}
public override string Sound() {
return name + ": woof";
}
}
public class Cat : Animal {
public Cat(string name) : base(name) {}
public override string Sound() {
return name + ": meow";
}
}
public class DogHouse : AnimalHouse<Dog> {
public DogHouse(params Dog[] dogs) : base(dogs) {}
}
public class CatHouse : AnimalHouse<Cat> {
public CatHouse(params Cat[] cats) : base(cats) {}
}
We use it like this:
public class AnimalCity {
List<GeneralAnimalHouse> houses;
public AnimalCity(params GeneralAnimalHouse[] houses) {
this.houses = houses.ToList();
}
public List<string> CitySounds() {
var random = new Random();
return houses.SelectMany(house => house.HouseSounds())
.OrderBy(x => random.Next())
.ToList();
}
}
public class MainClass {
public static void Main() {
var fluffy = new Cat("Fluffy");
var miu = new Cat("Miu");
var snuffles = new Cat("Snuffles");
var snoopy = new Dog("Snoopy");
var marley = new Dog("Marley");
var megan = new Dog("Megan");
var catHouse = new CatHouse(fluffy, miu, snuffles);
var dogHouse = new DogHouse(snoopy, marley, megan);
var animalCity = new AnimalCity(catHouse, dogHouse);
foreach (var sound in animalCity.CitySounds()) {
Console.WriteLine(sound);
}
}
}
Output:
Miu: meow
Snoopy: woof
Snuffles: meow
Fluffy: meow
Marley: woof
Megan: woof
Notes:
I added names so it's clear that the method references carry their owner's data with them, for those unfamiliar with delegates.
The required using statements for this code are System, System.Collections.Generic, and System.Linq.
You can try it here: https://dotnetfiddle.net/6qkHL3#
A version that makes GeneralAnimalHouse a subclass of AnimalHouse<Animal> can be found here: https://dotnetfiddle.net/XS0ljg
At first, I have a parent class like:
public class Father {
// skip ...
}
And these are two classes that inherit from Father. But Method_A only belongs to Child_A instead of Child_B.
public class Child_A : Father {
// skip ...
public void Method_A { ... }
}
public class Child_B : Father {
// skip ...
}
Finally, I try to create a variable can be assigned dynamically to
public class MyClass {
public Father dynamicObject;
public void MyMethod {
dynamicObject = new Child_A(); // Sometimes will be `Child_B`.
if (...) { // only `Child_A` can pass, I promise
dynamicObject.Method_A(); // Error here.
}
}
The error like below:
Type 'Father' does not contain a definition for 'Method_A' and no extension method 'Method_A' of type 'Father' could be found. Are you missing an assembly reference?
I had tried var type for dynamicObject, but we must set the var type in local scope.
public class MyClass {
public var dynamicObject; // It's not allow.
// ...
}
Use a cast to check the type of the dynamicObject:
Child_A childA = dynamicObject as Child_A;
if (childA != null)
{
childA.Method_A();
}
or with C# 6 and Null-conditional operator:
Child_A childA = dynamicObject as Child_A;
childA?.Method_A();
also is with an explicit (Child_A) cast could be used but I prefer the first approach.
if (dynamicObject is Child_A) {
((Child_A)dynamicObject).Method_A();
}
with C#7 and Pattern Matching like #Zbigniew suggested:
if (dynamicObject is Child_A child) {
child.Method_A();
}
Try to replace
dynamicObject.Method_A();
by
((Child_A)dynamicObject).Method_A();
i thing, It makes more sense to use the Method_A over the interface. while number of methods and classes increases, it will be easier to manage
public class Father { }
public class Child_A : Father, IMethodOwner { public void Method_A() { }}
public class Child_B : Father{ }
public interface IMethodOwner { void Method_A(); }
public class MyClass
{
public Father dynamicObject;
public void MyMethod() {
var obj = dynamicObject as IMethodOwner;
if(obj != null)
obj.Method_A();
}
}
I'm trying to create a class structure like this:
public abstract class ParentClass
{
protected virtual void BuildQueries()
{
var Engine = new FileHelperEngine(typeof(TopType));
DataPoints = Engine.ReadFile(ResumeName) as TopType[];
}
protected Parent TopType;
}
public class ChildClass : ParentClass
{
protected override Child TopType
}
and the types:
public abstract class Parent
{
//some class members here
}
public class Child : Parent
{
//some class members here
}
I think there's an easy answer here, but I'm just too new to C# to figure out what I should be googling. I've tried using generics and I just can't get it right.
I know that without the inheritance I'd write
var Engine = new FileHelperEngine(typeof(Parent));
But this is the part of the inheritance that I'm struggling to figure out.
Sorry I failed to mention that FileHelperEngine references the FileHelpers C# library
I do think you're looking for generics, but I'm not totally sure because your question is not clear...
public abstract class ParentClass<T> where T : Parent
{
protected virtual void BuildQueries()
{
var Engine = new FileHelperEngine<T>();
var r = Engine.ReadFile(ResumeName);
}
protected T TopType { get; set; }
// (...)
}
public class ChildClass : ParentClass<Child>
{
// don't need to override anything, because your property is generic now
// which means it will be of type `Child` for this class
}
public class FileHelperEngine<T>
where T : Parent // this generic constraint might not be necessary
{
public T[] ReadFile(string name)
{
}
}
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! :)
I need a method that creates an empty clone of an object in a base class? For instance:
public class ChildClass : ParentClass
{
public ChildClass()
{
}
}
public class ParentClass
{
public SomeMethod()
{
// I want to create an instance of the ChildClass here
}
}
Up until now, we have an abstract method defined in the parent class. And, all of the child classes implement them. But, the implementation is the same for all, just a different type.
public class ChildClass : ParentClass
{
public ChildClass()
{
}
public ParentClass CreateEmpty()
{
return new ChildClass();
}
}
public class ParentClass
{
public SomeMethod()
{
// I want to create an instance of the ChildClass here
ParentClass empty = CreateEmpty();
}
public abstract ParentClass CreateEmpty();
}
Is there any way to do this from the parent class so that I don't have to keep implementing the same logic for each different child class? Note that there may be more levels of inheritance (i.e. ChildChildClass : ChildClass : ParentClass).
If using reflection isn't a problem to you, you could do it using Activator class:
//In parent class
public ParentClass CreateEmpty()
{
return (ParentClass)Activator.CreateInstance(this.GetType());
}
This will return empty object of the type you want. Notice that this method does not need to be virtual.
On the other hand, I think that your current approach is perfectly fine, few more lines of code aren't so bad.
You can make a deep clone of the object using the binary serializer.
EDIT: Just noticed the word "empty" next to clone (which I thought was an oxymoron). Leaving this response up anyhow hoping it will help others that find this question because they are looking to do a regular clone.
This is somewhat experimental. I don't know whether this will lead to a cyclic dependency. Haven't touched C# for some months.
public class ParentClass<T> where T : ParentClass<T>, new() { // fixed
public ParentClass() {
var x = new T(); // fixed, was T.new()
}
}
public class ChildClass : ParentClass<ChildClass> {
public ChildClass() { }
}
Otherwise go for the ReflectionCode by Ravadre.
I'm using the following pattern.
Pros:
This pattern secure the type-safety of cloning in private and public sides of classes.
The output class will be always correct.
You never forgot override the "clone" method. The "MyDerivedClass" never returns another class than the "MyDerivedClass".
Cons:
For one class, you need create one interface and two classes (prototype and final)
Sample:
// Common interface for cloneable classes.
public interface IPrototype : ICloneable {
new IPrototype Clone();
}
// Generic interface for cloneable classes.
// The 'TFinal' is finaly class (type) which should be cloned.
public interface IPrototype<TFinal> where TFinal : IPrototype<TFinal> {
new TFinal Clone();
}
// Base class for cloneable classes.
// The 'TFinal' is finaly class (type) which should be cloned.
public abstract class PrototypeBase<TFinal> : IPrototype<TFinal> where TFinal : PrototypeBase<TFinal> {
public TFinal Clone() {
TFinal ret = this.CreateCloneInstance();
if ( null == ret ) {
throw new InvalidOperationException( "Clone instance was not created." );
}
this.FillCloneInstance( ret );
return ret;
}
// If overriden, creates new cloned instance
protected abstract TFinal CreateCloneInstance();
// If overriden, fill clone instance with correct values.
protected abstract void FillCloneInstance( TFinal clone );
IPrototype IPrototype.Clone() { return this.Clone(); }
object ICloneable.Clone() { return this.Clone(); }
}
// Common interface for standalone class.
public interface IMyStandaloneClass : IPrototype<IMyStandaloneClass> {
string SomeText{get;set;}
string SomeNumber{get;set;}
}
// The prototype class contains all functionality exception the clone instance creation.
public abstract class MyStandaloneClassPrototype<TFinal> : PrototypeBase<TFinal>, IMyStandaloneClass where TFinal : MyStandaloneClassPrototype<TFinal> {
public string SomeText {get; set;}
public int SomeNumber {get; set}
protected override FillCloneInstance( TFinal clone ) {
// Now fill clone with values
clone.SomeText = this.SomeText;
clone.SomeNumber = this.SomeNumber;
}
}
// The sealed clas contains only functionality for clone instance creation.
public sealed class MyStandaloneClass : MyStandaloneClassPrototype<MyStandaloneClass> {
protected override MyStandaloneClass CreateCloneInstance() {
return new MyStandaloneClass();
}
}
public interface IMyExtendedStandaloneClass : IMyStandaloneClass, IPrototype<IMyExtendedStandaloneClass> {
DateTime SomeTime {get; set;}
}
// The extended prototype of MyStandaloneClassPrototype<TFinal>.
public abstract class MyExtendedStandaloneClassPrototype<TFinal> : MyStandaloneClassPrototype<TFinal> where TFinal : MyExtendedStandaloneClassPrototype<TFinal> {
public DateTime SomeTime {get; set;}
protected override FillCloneInstance( TFinal clone ) {
// at first, fill the base class members
base.FillCloneInstance( clone );
// Now fill clone with values
clone.SomeTime = this.SomeTime;
}
}
public sealed class MyExtendedStandaloneClass : MyExtendedStandaloneClassPrototype<TFinal> {
protected override MyExtendedStandaloneClass CreateCloneInstance() {
return new MyExtendedStandaloneClass
}
}