Generic classes an Inheritance - c#

I have 2 classes (classA and classB) that both inherits from same class (classC). Now I need create new generic class (classAA) that inherits List of A or B. Is it possible to call methods of classC in classAA.
public class classC
{
//...
}
public class classA : classC
{
//...
}
public class classB : classC
{
//...
}
public class classAA<T> : List<T>
{
//...
}

It's generally not a good idea to inherit from List<T>. 95% of time you should prefer composition over inheritance. See for example: Why not inherit from List<T>?
Most probably you are looking for something like:
public class classAA<T>
where T : ClassC
{
public List<T> MyList { get; set; }
public void Foo()
{
foreach (var item in this.MyList)
{
item.MethodOfClassC();
}
}
}

I believe you want something like this. Assumming:
class classC
{
public void DrawObject() { }
}
you can put constraint on T that it will be classC or its derivatives:
class classAA<T> : List<T> where T : classC
{
public void SomeMethod()
{
foreach (var item in this.Cast<classC>())
{
// here you can call item.DrawObject()
}
}
}

Related

Problem with adding items to a generic list

I have the following interface
public interface IInterface
{
int GetId();
}
ClassA is a generic class but T should implement IInterface
public class ClassA<T> where T : IInterface {
}
ClassB implements IInterface
public class ClassB : IInterface {
public int GetId() {
return 1;
}
}
ClassC is where my problem is, namely adding items to the list.
public class ClassC {
List<ClassA<IInterface>> list = new List<ClassA<IInterface>>();
public void Add<T>(ClassA<T> item) where T : IInterface {
list.Add(item);
}
}
The code above gives the following error which makes sense
cannot convert from 'Program.ClassA<T>' to'Program.ClassA<Program.IInterface>'
The core of the problem is in the Add() method where my goal is to be able to add any type of ClassA. I am not sure how to design this in order to achieve the following
ClassC classC = new ClassC();
ClassA<ClassB> classA = new ClassA<ClassB>();
classC.Add(classA);
Any ideas?
What about using Covariant Generic Type Argument.
public interface IInterface
{
int GetId();
}
// Contra-variant and covariant generic type argument can be used only in interfaces and delegates
public interface IClassA<out T> where T : IInterface
{
}
public class ClassA<T> : IClassA<IInterface> where T : IInterface { }
public class ClassB : IInterface
{
public int GetId()
{
return 1;
}
}
public class ClassC
{
List<IClassA<IInterface>> list = new List<IClassA<IInterface>>();
public void Add(IClassA<IInterface> item)
{
list.Add(item);
}
}
public class Test
{
public static void Run()
{
ClassC classC = new ClassC();
ClassA<ClassB> classA = new ClassA<ClassB>();
classC.Add(classA);
}
}
Depending on the specifics of your design, you may be able to split ClassA in two:
public abstract class ClassA {
//Stuff that only works in terms of IInterface,
//maybe with some abstract methods, required constructors, etc
}
public class ClassA<T> : ClassA where T : IInterface {
//Stuff specific to T
}
You then store ClassAs in your list and cast them to their known concrete type as/when you know what that is and need to work in those terms (e.g. to be able to call ClassA<T> specific functionality)

Generic Method for List of Generic Classes

I have problem.
For example, considering these 4 classes.
public abstract ParentContainer<T> where T: Parentfoo
{
public List<T> fooList;
}
//Let there be many different ChildContainers with different types.
public class ChildContainer : ParentContainer<ChildFoo>
{
}
public abstract class ParentFoo
{
public string name;
}
public class ChildFoo : ParentFoo
{
}
How can I write a method which accepts a List of any arbitrary ChildContainers as a parameter,
which do operation on their fooLists?
Is it even possible?
Additional Explanation, there are many different childs of ParentContainer,
each with a List of a different child of foo.
public class ChildContainerB : ParentContainer<ChildFooB>{}
public class ChildContainerC : ParentCOntainer<ChildFooC>{}
...
public class ChildFooB : ParentFoo;
public class ChildFooC : ParentFoo;
Then I need a method something like this
//X means it can be any arbitrary ChildContainer
public void method(List<ChilContainerX> list)
{
foreach(ChildContainerX x in list)
{
print(x.fooList.Last().name);
}
}
So what you are asking isn't possible because you need a concrete type for the List<>. There are a couple of workarounds though.
Use List<object>. This is obviously not great because as it means you lose type checking completely and could end up with anything being added to the list. So for that reason, I wouldn't recommend this approach.
Make ParentContainer<> implement a marker interface. For example:
public interface IParentContainer
{
}
public abstract class ParentContainer<T> : IParentContainer
where T: ParentFoo
{
//snip
}
And now you can have your list like this:
var containers = new List<IParentContainer>
{
new ChildContainer(),
new ChildContainer2()
};
Unless I misunderstand the question, you want something like this ...
public void DoStuffWith<T>(List<ParentContainer<T>> containers) where T : Parentfoo
{
//TODO: implement
}
This would work on objects of type ...
List<ParentContainer<ParentFoo>>
List<ParentContainer<ChildFoo>>
where ChildFoo : ParentFoo
and solves the issue of "List<ParentContainer<ParentFoo>> does not implement IEnumerable<ParentContainer<ChuldFoo>>" which I suspect is the compiler you are seeing.
Taking this a step further something like ....
public void DoStuffWith<ContainerT,ElementT>(List<ContainerT<ElementT>> containers)
where ContainerT : ParentContainer
where ElementT : Parentfoo
{
//TODO: implement
}
... likely over complicates the issue but i suspect is what you are trying to achieve.
At this point I would question the data structures you have and give them some common parent for example ...
public class ParentContainer<T> : IEnumerable<T> { ... }
public class ChildContainer<T> : ParentContainer<T>, IEnumerable<T> { ... }
Since both implement IEnumerable you can now do ...
public void DoStuffWith<T>(IEnumerable<T> containers) where T : ParentFoo
{
//TODO: implement
}
This avoids the need to be concerned with the collection type at all.
class Program
{
static void Main(string[] args)
{
List<ParentContainer<ChildFoo>> ca = new List<ParentContainer<ChildFoo>>();
ProcessContainers processor = new ProcessContainers();
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerB { fooList = new List<ChildFoo>() });
processor.Process(ca);
}
}
public abstract class ParentContainer<T> where T: ParentFoo
{
public List<T> fooList;
}
//Let there be many different ChildContainers with different types.
public class ChildContainerA : ParentContainer<ChildFoo>
{
}
public class ChildContainerB : ParentContainer<ChildFoo>
{
}
public class ProcessContainers
{
public void Process<T>(List<ParentContainer<T>> childContainers) where T : ParentFoo
{
foreach(var item in childContainers)
{
foreach(var foo in item.fooList)
{
foo.Porcess();
}
}
}
}
public abstract class ParentFoo
{
public string name;
public abstract void Porcess();
}
public class ChildFoo : ParentFoo
{
public override void Porcess()
{
//Do some processing
}
}

C# Generics - Classes implementing other generic classes

I have a
public class A<T> where T : IBase
{
//Does something
}
I need a second class that behaves like a collection of class A
public class B<A<T>> : IEnumerable<A<T>> where T : IBase
{
}
The problem is that I do not want to create classes like
public class B<A<MyCustomObjectP>> : IEnumerable<A<MyCustomObjectP>>
{
}
public class C<A<MyCustomObjectQ>> : IEnumerable<A<MyCustomObjectQ>>
{
}
and so on.. I would like to let the CustomObject be a generic type parameter that implements IBase.
I found that even doing this is illegal:
public class B<T, U> : IEnumerable<T> where T : A<U> where U : IBase
{
}
How could I achieve this type of behaviour, if this is illegal? Is there a better design pattern of sorts that might help?
The IBase constraint is defined on A<T>, so it must be defined again on all generic classes, that want to use A<U> (using U to distinguish from T in A<T> class definition, but it can be called anything). You should be able to do simply:
public class B<T> : IEnumerable<A<T>> where T : IBase { ... }
You wrote that you need a second class that behaves like a collection of class A.
Since you have other classes (like B) inheriting from IBase as well, which you want to add, you can make the collection a collection of IBase.
Hence the solution would look like this (note that I have used List but you can easily replace that by IEnumerable - but then you have to implement methods like .Add yourself):
void Main()
{
var items = new CollectionOf<IBase>(); // create list of IBase elements
items.Add(new A() { myProperty = "Hello" }); // create object of A and add it to list
items.Add(new B() { myProperty = "World" }); // create object of B and add it to list
foreach(var item in items)
{
Console.WriteLine(item.myProperty);
}
}
// this is the collection class you asked for
public class CollectionOf<U>: List<U>
where U: IBase
{
// collection class enumerating A
// note you could have used IEnumerable instead of List
}
public class A: IBase
{
// class A that implements IBase
public string myProperty { get; set; }
}
public class B: IBase
{
// class B that implements IBase too
public string myProperty { get; set; }
}
public interface IBase {
// some inteface
string myProperty { get; set; }
}

How do I make a constructor only accessible by base class?

If I want a constructor that is only accessible from child classes I can use the protected key word in the constructor.
Now I want the opposite.
My child class should have an constructor that can be accessed by its base class but not from any other class.
Is this even possible?
This is my current code. the problem is that the child classes have a public constructor.
public abstract class BaseClass
{
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(dataTable);
}
public static BaseClass CreateInstance(DataSet dataSet)
{
return new Child2(dataSet);
}
}
public class Child1 : BaseClass
{
public Child1(DataTable dataTable)
{
}
}
public class Child2 : BaseClass
{
public Child2(DataSet dataSet)
{
}
}
I think you have two options:
Make the child constructor internal. This means it will be accessible from all types in the same assembly, but that should be enough in most cases.
Make the child classes nested in the base class:
public abstract class BaseClass
{
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(dataTable);
}
private class Child1 : BaseClass
{
public Child1(DataTable dataTable)
{
}
}
}
This way, BaseClass can use the constructor, but no other outside type can do that (or even see the child class).
I think I just solved it by myself. After reading svicks solution with nested classes, I thought why not use an protected nested class as an argument?
Nobody from outside is able to create an instance of Arg and the public contructors from my child classes can only be used by BaseClass which can create Arg<T> instances.
public abstract class BaseClass
{
protected class Arg<T>
{
public T Value { get; set; }
public Arg(T value) { this.Value = value; }
}
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(new Arg<DataTable>(dataTable));
}
public static BaseClass CreateInstance(DataSet dataSet)
{
return new Child2(new Arg<DataSet>(dataSet));
}
}
public class Child1 : BaseClass
{
public Child1(Arg<DataTable> arg) : this(arg.Value) { }
private Child1(DataTable dataTable)
{
}
}
public class Child2 : BaseClass
{
public Child2(Arg<DataSet> arg) : this(arg.Value) { }
public Child2(DataSet dataSet)
{
}
}
Answer to the question is "NO"
There is no such thing exists in the OOP that allow child class constructor to visible only to the Base Class of it...
One could enforce the desired behavior at run-time by having the base constructor accept a ref parameter, and do something like (not threadsafe):
private int myMagicCounter;
public DerivedClass makeDerived(whatever) // A factory method
{
DerivedClass newThing;
try
{
... do whatever preparation
newThing = new DerivedClass(ref myMagicCounter, whatever);
}
finally
{
... do whatever cleanup
}
return newThing;
}
BaseClass(ref int magicCounter, whatever...)
{
if (magicCounter != myMagicCounter)
throw new InvalidOperationException();
myMagicCounter++;
if (magicCounter != myMagicCounter)
throw new InvalidOperationException();
}
Note that it will be impossible for a derived class constructor call to get control without having done the factory method's preparation, or to return control to its caller without doing the factory method's cleanup. There will, however, be nothing to prevent the derived-class constructor from passing its partially-constructed instance to outside code which may do whatever it likes with it for an arbitrary amount of time before returning control to the factory method.
Pass and register a factory delegate from the type initializer of derived classes then you just get the job done:
public abstract class BaseClass {
static readonly Dictionary<Type, Delegate>
m_factories = new Dictionary<Type, Delegate> { };
public static BaseClass CreateInstance(DataTable dataTable) {
var type = typeof(Child1);
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
return (Child1)m_factories[type].DynamicInvoke(dataTable);
}
public static BaseClass CreateInstance(DataSet dataSet) {
var type = typeof(Child2);
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
return (Child2)m_factories[type].DynamicInvoke(dataSet);
}
protected static void AddFactory<TArgs, T>(Func<TArgs, T> factory) {
m_factories.Add(typeof(T), factory);
}
}
public class Child1:BaseClass {
Child1(DataTable dataTable) {
}
static Child1() {
BaseClass.AddFactory((DataTable dt) => new Child1(dt));
}
}
public class Child2:BaseClass {
Child2(DataSet dataSet) {
}
static Child2() {
BaseClass.AddFactory((DataSet ds) => new Child2(ds));
}
}
public static class TestClass {
public static void TestMethod() {
var child2 = BaseClass.CreateInstance(new DataSet { });
var child1 = BaseClass.CreateInstance(new DataTable { });
}
}
If all of the derived classes inherited from the base class directly then don't you worry about the collision of registration -- no body can access a constructor from another class.
For TArgs of Func<TArgs, T> you might want to declare it like variadic generic arguments although it's just not a feature of C♯, Tuple is one of the approaches to simulate it. For more information on this topic, you might want to have a look at:
Simulate variadic templates in c#

Restricting subclasses from inheriting certain methods of base class

using System;
public class Base
{
public Base()
{
}
public void M1()
{
}
public void M2()
{
}
public void M3()
{
}
}
public class Derived : Base
{
//this class should get only method 1
}
public class SecondDerived : Base
{
//this class should get only method 2 and method3
}
The requirement is : the base class contains the 3 methods M1, M2, M3.
The derived class should inherit only M1 and SecondDerived should inherit only M2 and M3.
How can this be done?
You cannot selectively inherit methods like this. A derived class automatically inherits all public methods of the base class. I suggest you to split the Base class into two classes:
public class Base1
{
public Base1()
{
}
public void M1()
{
}
}
public class Base2
{
public void M2()
{
}
public void M3()
{
}
}
public class First : Base1
public class Second : Base2
You cannot do it in this way. Inheritance implies an "IS A" relationship.
If SecondDerived would not have a M1() then it would not be compatible with a reference to a the class Base.
So maybe you shouldn't be using inheritance for whatever problem you're solving.
It is not possible to do what you want with inheritance.
It seems you have no intention of overriding, you simply want to "inherit" behavior from the base class selectively. You could do this using a "has a" relationship:
public class Base
{
internal Base() {} //mark constructor as internal so it can not be used outside your assembly if necessary
public Foo Mehtod1() {...}
public Foo Mehtod2() {...}
public Foo Mehtod3() {...}
}
Then simply do the following:
class A
{
private Base internalBase;
public A() { this.internalBase = new Base(); }
public Foo Method1() { return this.internalBase.Method1(); }
}
class B
{
private Base internalBase;
public A() { this.internalBase = new Base(); }
public Foo Method2() { return this.internalBase.Method2(); }
public Foo Method3() { return this.internalBase.Method3(); }
}
UPDATE: A possible alternative solution is to make your Base class methods virtual and override them all in your derived classes, throwing NotSupportedExceptions in those methods that you do not want the class to make available. I don't really like this solution but it has the advantage of not loosing the polyphormism inheritance gives you which might be useful if you have some core base functionality which all derived classes will share (in your example you seem to imply they wont).
It is possible by adding Obsolete attribute
public class A
{
public virtual void M1() { }
public void M2() { }
public void M3() { }
}
public class B : A
{
[Obsolete("You can not use this", true)]
public sealed override void M1()
{
}
}
public class C : B
{
public void Test()
{
// Will show error
base.M1();
}
}

Categories

Resources