I have a base class like this:
class FooBase
{
public bool Do(int p) { /* Return stuff. */ }
}
And a child class like this:
class Foo<T> : FooBase
{
private Dictionary<T, int> Dictionary;
public bool Do(T p)
{
int param;
if (!Dictionary.TryGetValue(p, out param))
return false;
return base.Do(param);
}
}
If the user creates a Foo<string> object called "fooString", then he can call both fooString.Do(5) and fooString.Do("test") but if he creates a Foo<int> object called "fooInt", he can only call the Do method of the derived class. I prefer the second no matter what the T is.
The Do methods in both of these classes essentially do the same thing. The one in the derived class gets an integer from a Dictionary<T, int> using the given parameter and calls the Do method of the base class using it.
That's why I want to hide the Do method of the FooBase in Foo<T>. How can I achieve this or something similar? Any design advice to overcome this would also be nice.
but if he creates a Foo<int> object called "fooInt", he can only call the Do method of the derived class.
No, that's not true. If the declared type of the variable is FooBase, it will still call the FooBase method. You're not really preventing access to FooBase.Do - you're just hiding it.
FooBase foo = new Foo<int>();
foo.Do(5); // This will still call FooBase.Do
Full sample code to show that:
using System;
class FooBase
{
public bool Do(int p) { return false; }
}
class Foo<T> : FooBase
{
public bool Do(T p) { return true; }
}
class Test
{
static void Main()
{
FooBase foo1 = new Foo<int>();
Console.WriteLine(foo1.Do(10)); // False
Foo<int> foo2 = new Foo<int>();
Console.WriteLine(foo2.Do(10)); // True
}
}
That's why I want to hide the Do method of the FooBase in Foo.
You need to think about Liskov's Substitutability Principle.
Either Foo<T> shouldn't derive from FooBase (use composition instead of inheritance) or FooBase.Do shouldn't be visible (e.g. make it protected).
You could build a base class that is abstract with a protected Do method, and rewrite your current FooBase class to inherit from Foo<T>:
public abstract class FooBaseAbstract
{
protected bool Do(int p)
{
return true;
}
}
// You can use this one just as your current FooBase class
public class FooBase : Foo<int>
{
}
public class Foo<T> : FooBaseAbstract
{
public bool Do(T p)
{
if (true /* some test here */)
{
return base.Do(4);
}
return false;
}
}
(of course change the class names)
Related
abstract class Foo
{
private readonly FooAttributeCollection attributes;
public Foo(FooAttributeCollection attributes)
{
this.attributes = attributes;
}
}
class FooAttributeCollection
{
public FooAttributeCollection(Foo owner)
{
}
}
class Bar : Foo
{
public Bar() : base(new FooAttributeCollection(this))
{
}
}
Supposing that I have to write a code like above. and the classes Foo and FooAttributeCollection cannot be modified.
When I write Bar class like that, an error mentioned below:
'this' keyword cannot be used in this context.
occurs near the line base(...)
Is there any good idea to handle with this matter?
If Foo and FooAttributeCollection can't be modified, this code seems to be a bad design.
To instantiate a derivated Foo class you must instantiate FooAttributeCollection before and to instantiate FooAttributeCollection you must instantiate the same derivated Foo class.
Its a endless circular dependency impossible to resolve without 'cheating'
perhaps this problem can be resolve by refection (as say by Uwe Keim), or by using real proxy/dynamic proxy to create a proxy of DerivedClass.
Why don't affect attributes in abstract class ? If you want in FooAttributeCollection you can cast owner in Bar class.
abstract class Foo
{
private readonly FooAttributeCollection attributes;
public Foo(FooAttributeCollection attributes=null)
{
if(attributes = null) {attributes = new FooAttributeCollection(this);}
this.attributes = attributes;
}
}
class FooAttributeCollection
{
public FooAttributeCollection(Foo owner)
{
var ownerInBar = owner as Bar;
}
}
class Bar : Foo
{
public Bar() : base()
{
}
}
You can't write:
public Bar() : base(new FooAttributeCollection(this))
Because this, the current object, must be put in the implementation of a method, not in the method signature: here you have no access to the current instance of the object.
You can't do a such thing in every method declaration because you are out of the implementation scope, you are in the type def scope i.e. in the "interface" of the class, in its definition.
The use of calling base or side constructor with base or this keyword is a particular language construction to pass parameters that are not the instance of the class itself.
You can use the #Tohm solution to solve your goal.
the class needs to be constructed before you can access the this keyword.
You can try the bellow.
class Bar : Foo
{
private readonly FooAttributeCollection attributes;
public Bar() : base(null)
{
var attributes = new FooAttributeCollection(this);
}
}
Try this way:
public class Bar : Foo
{
public Bar(FooAttributeCollection attributes) : base(attributes)
{
}
}
Other Example:
public class BaseClass
{
int num;
public BaseClass(int i)
{
num = i;
Console.WriteLine("in BaseClass(int i)");
}
}
public class DerivedClass : BaseClass
{
// This constructor will call BaseClass.BaseClass(int i)
public DerivedClass(int i) : base(i)
{
}
}
I have a class Foo that has a field _customObject that must be initialized. I also have a class Bar that inherits from Foo:
public abstract class Foo
{
protected CustomObject _customObject;
public Foo()
{
// Do stuff
}
// Other methods that use _customObject
}
public class Bar : Foo
{
// Constructor and other methods
}
I can not initialize the object _customObject in Foo because every child inherited contains a different child of CustomObject, so it must be initialized in every child class:
public class Bar : Foo
{
public Bar()
{
_customObject = new CustomObjectInherited1();
}
}
public class Baz : Foo
{
public Baz()
{
_customObject = new CustomObjectInherited2();
}
}
Other people are going to implement new classes that inherit from Foo, so I was wondering if there is a way that an error in build time is shown, similar to when an abstract method is not implemented. If CustomObject is not initialized, a NullReferenceException will be thrown due to the use of the _customObject variable, ending in an application crash.
You can add a parameter to your Foo constructor:
public abstract class Foo
{
protected CustomObject _customObject;
public Foo(CustomObject obj)
{
// Do stuff
_customObject = obj;
}
// Other methods that use _customObject
}
Your derived classes will then be forced to call it, passing in a CustomObject, or something derived from it:
public class Bar : Foo
{
public Bar():base(new CustomObjectInherited1())
{
}
}
Not calling the base constructor will result in a compile time error. This doesn't entirely protect you, as someone could still pass null to the base constructor, but at least they'll have an explanation as to why they're getting a NullReferenceError at runtime.
You can force it by creating a abstract method which requires child classes to override it.
public abstract class Foo
{
protected abstract CustomObject CreateCustomObject();
}
public class Bar : Foo
{
protected override CustomObject CreateCustomObject()
{
return new BarCustomObject();
}
}
Or my favorite solution: Enforce it by generic constraints.
public abstract class Foo<T> : where T : CustomObject, new()
{
protected T _customObject;
public Foo()
{
this.CustomObject = new T();
}
}
public class Bar : Foo<BarCustomObject>
{
}
The answer provided by "James Thorpe" is correct (I've upvoted it already), but I wanted to share just another option here:
You could mark your class as abstract and introduce an abstract property instead of the "_customObject" field. That way, at least the first initializer will be forced to implement it. The downside is that you'll loose the enforcement on subsequent level subclasses:
public abstract class Foo
{
protected abstract CustomObject CustomObject {get; }
public Foo()
{
// Do stuff
}
// Other methods that use _customObject
}
public class Bar : Foo
{
// Constructor and other methods
protected override CustomObject CustomObject
{
get { return "X"; }
}
}
Also, with the first solution it's possible to validate the passed in value in the constructor - though, that'll be a runtime validation.
I'm not sure if this is possible at all, looking for some clarification.
I have a class structure like this:
public class FooBase
{
//Some base class
}
public class BarBase
{
//Some base class
}
public class Foo : FooBase
{
//Implementation
}
public class Bar : BarBase
{
//Implementation
}
public abstract class FooBarHolderAbstract<T, V> where T: FooBase where V: BarBase
{
}
public class MyFooBarHolderImpl : FooBarHolderAbstract<Foo, Bar>
{
}
public class FooBarTest
{
public void DoSomethingWithFooBar<T>() where T : FooBarHolderAbstract<FooBase, BarBase>
{
//Do something tith the obj
}
public void RunTest()
{
//This doesn't work, compiler says MyFooBarHolder is not convertible to FooBarHolderAbstract<FooBase, BarBase>
DoSomethingWithFooBar<MyFooBarHolderImpl>();
}
}
In the FooBarTest class, I'd like to create a method which accepts a generic parameter, which inherits from the abstract class having two generic parameters. The class MyFooBarHolderImpl extends the abstract base class and specifies its generic parameters with types which are inheriting from the abstract class' generic parameter types.
When I try to call this method (DoSomethingWithFooBar()) the compiler tells me that the type MyFooBarHolderImpl must be convertible to FooBarHolderAbstract
Is this something which cannot be done at all, or am I missing a concept/syntax?
Thanks in advance!
Well, it can't be done directly - a FooBarHolderAbstract<Foo, Bar> isn't a FooBarHolderAbstract<FooBase, BarBase>. It's not clear whether or not you could logically have that, because we don't know what's in the abstract class.
You're basically looking for generic covariance, but that isn't supported on classes anyway - so you may want to introduce an interface:
public interface IFooBarHolder<out T, out V>
where T: FooBase
where V: BarBase
{
// Define what you need in here
}
public abstract class FooBarHolderAbstract<T, V> : IFooBarHolder<T, V>
where T : FooBase
where V : BarBase
{
}
At that point, you can change FooBarTest to:
public void DoSomethingWithFooBar<T>() where T : IFooBarHolder<FooBase, BarBase>
{
//Do something with the obj
}
... because an IFooBarHolder<Foo, Bar> is an IFooBarHolder<FooBase, BarBase>.
However, this only works if you can define all your operations for the interface which use T and V in "out" positions, e.g. return types from methods. If you ever need them in "input" positions, e.g. as method parameters, you're stuck - because a method expecting a Foo can't handle any other kind of FooBase.
It doesn't clear, what are you going to do in DoSomethingWithFooBar, since you don't pass any parameter, but here are another options:
public class FooBarTest
{
public void DoSomethingWithFooBar<TFooBase, TBarBase>(FooBarHolderAbstract<TFooBase, TBarBase> obj)
where TFooBase : FooBase
where TBarBase : BarBase
{
//Do something tith the obj
}
public void RunTest()
{
DoSomethingWithFooBar<Foo, Bar>(new MyFooBarHolderImpl());
}
}
or
public class FooBarTest
{
public void DoSomethingWithFooBar<TFooBase, TBarBase, THolder>()
where TFooBase : FooBase
where TBarBase : BarBase
where THolder : FooBarHolderAbstract<TFooBase, TBarBase>
{
//Do something tith the obj
}
public void RunTest()
{
DoSomethingWithFooBar<Foo, Bar, MyFooBarHolderImpl>();
}
}
You have to write your FooBarTest as below. You have to define T for DoSomethingWithFooBar<T> as FooBarHolderAbstract<Foo, Bar>
public class FooBarTest
{
public void DoSomethingWithFooBar<T>() where T : FooBarHolderAbstract<Foo, Bar>
{
//Do something tith the obj
}
public void RunTest()
{
DoSomethingWithFooBar<MyFooBarHolderImpl>();
}
}
I have a Function in C# and it have to return the type of the Class. Also in subclasses which extends the class.
Like:
public class A
{
public typeof(this) Method()
{
//Code
}
}
public class B : A {
public override typeof(this) Method() {
//Code
}
}
So the Method in class A should have the return type A. And the Method in class B should have the return tpye B.
Is there a way to do it?
No, this isn't possible. What you're asking for is called a covariant return type, but C# doesn't support this. The closest you can get is either this:
public class A
{
public virtual A Method()
{
//Code returning an A
}
}
public class B : A
{
public override A Method()
{
//Code returning a B
}
}
Which is legal because every B is also an A, or you can use generics instead of inheritance:
public class Foo<T>
{
public virtual T Method()
{
//Code
}
}
And then you can have Foo<A> and Foo<B> -- however, Foo cannot depend on any specifics of T. You can combine this with inheritance, which will sort of achieve what you want:
public class A : Foo<A>
{
// And now A has a Method that returns A
}
public class B : Foo<B>
{
// And now B has a Method that returns B
}
But the problem with this approach is that you will have a hard time actually implementing Method in a meaningful way, because in Foo you cannot use anything specific to the type. To make this explicit, you could make Method abstract:
public abstract class Foo<T>
{
public abstract T Method();
}
public class A : Foo<A>
{
public override A Method()
{
// Code
}
}
public class B : Foo<B>
{
public override B Method()
{
// Code
}
}
I'm having a hard time imagining a scenario where you can actually make use of this, but at least it meets the requirements.
Last but not least, you are not required to use inheritance -- does B really need to derive from A or could you inherit from some common base that does not use Method?
Depending on what your method is trying to do, it might be possible to achieve what you want by using extension methods.
public class A { }
public class B : A { }
public static class AExtension {
public static T Method<T>(this T target) where T: A {
// do your thing here.
return target; // or, return a new instance of type T.
}
}
You can then call Method() and let C# infer the generic argument:
var a = new A();
a = a.Method(); // C# will infer T as A.
var b = new B();
b = b.Method(); // C# will infer T as B.
The downside to this approach is, of course, that you cannot access non-public members of your classes in Method(), unless you use reflection.
There is a way to do this, actually.
class A {
public A Method () { ... return this; }
}
class B : A {
new public B Method () => (B)base.Method();
// or { base.Method(); return this; }
}
Make sure you only use this if you know that the base returns this.
Suppose you have two classes, as in the example below.
How would you modify SplitObject such that it always returns an object of type t, such as in Main(), where it should return an object of type DerivedClass?
I'm guessing the solution would involve reflection? I haven't learned anything about reflection yet, so I don't know how this would work.
public class BaseClass
{
float _foo;
public BaseClass(float foo){_foo = foo}
public BaseClass SplitObject()
{
Type t = GetType();
// Do something with t
_foo = _foo/2f;
return new BaseClass(_foo); // I want to construct an
// object of type t instead
// of type BaseClass
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(float foo) : base(foo){}
}
class Program
{
static void Main()
{
BaseClass foo = new DerivedClass(1f);
BaseClass bar = foo.SplitObject(); // should return a DerivedObject
}
}
If you really wanted to use reflection, you could do something like:
return (BaseClass)Activator.CreateInstance(GetType(), _foo);
Of course, there is now an implicit contract that all derived classes must implement such a constructor. Unfortunately, such contracts cannot be specified in the current type-system; so violations will not be caught at compile-time. It would be much better to go with erash's idea. I would do something like:
//... Base class:
public BaseClass SplitObject()
{
_foo = _foo / 2f;
return NewInstance(_foo);
}
protected virtual BaseClass NewInstance(float foo)
{
return new BaseClass(foo);
}
//... Derived class:
protected override BaseClass NewInstance(float foo)
{
return new DerivedClass(foo);
}
No reflection required -- just make SplitObject() be virtual and implement it differently in your derived classes.
Another option would be to extract the Split behavior into an interface, say ISplittable<T>
public class BaseClass
{
public virtual BaseClass SplitObject()
{
BaseClass splitObject = new BaseClass();
//initialize the split object
return splitObject;
}
}
public class DerivedClass : BaseClass
{
public override BaseClass SplitObject()
{
DerivedClass derivedSplitObject = new DerivedClass();
//initialize the derived split object
return derivedSplitObject;
}
}
}
If you only want the code to appear in one place (better for maintenance, especially if there are many derived types), you will need to use reflection:
public class BaseClass
{
float _foo;
public BaseClass(float foo){_foo = foo;}
public BaseClass SplitObject()
{
Type t = GetType();
_foo = _foo / 2f;
//Find the constructor that accepts float type and invoke it:
System.Reflection.ConstructorInfo ci = t.GetConstructor(new Type[]{typeof(float)});
object o=ci.Invoke(new object[]{_foo});
return (BaseClass)o;
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(float foo) : base(foo) { }
}
class Program
{
static void Main()
{
BaseClass foo = new DerivedClass(1f);
//Cast the BaseClass to DerivedClass:
DerivedClass bar = (DerivedClass)foo.SplitObject();
}
}