I am a beginner in C# and cannot find out how to call a base constructor from within a subclass:
Base class:
public class LookupScript
{
protected Func<IEnumerable> getItems;
protected LookupScript()
{
//
}
public LookupScript(Func<IEnumerable> getItems) : this()
{
Check.NotNull(getItems, "getItems");
this.getItems = getItems;
}
My derived class:
public class PresenceLookup : LookupScript
{
public PresenceLookup() :base(??)
{
//
}
List<string> myMethod()
{
return null;
}
How can I pass myMethod to the base class?
Thank you
You can't, as myMethod is an instance method, and you can't access anything to do with the instance being created within the constructor initializer. This would work though:
public class PresenceLookup : LookupScript
{
public PresenceLookup() : base(MyMethod)
{
}
private static List<string> MyMethod()
{
return null;
}
}
That uses a method group conversion to create a Func<List<string>> that will call MyMethod.
Or if you don't need the method for anything else, just use a lambda expression:
public class PresenceLookup : LookupScript
{
public PresenceLookup() : base(() => null)
{
}
}
Related
This is probably a classic covariance/contravariance question, it looks like it should work but I'm probably missing a trick.
I'm attempting to return a less derived type from a factory method, but I find that I cannot cast the more specialized concrete instance to a less derived base type.
public class AnimalSettings { ... }
public class CatSettings : AnimalSettings { ... }
public interface IAnimalService<TSettings> { ... }
public abstract AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings { ... }
public class CatService : AnimalService<CatSettings> { ... }
Then, in a factory method I have:
public static IAnimalService<AnimalSettings> GetAnimalService(AnimalType selector)
{
switch (selector)
{
case AnimalType.Cat:
return (IAnimalService<AnimalSettings>) new CatService();
break;
}
}
and the intention is to be able to do the following:
var service = MyServiceFactory.GetAnimalService(AnimalType.Cat);
service.DoAnimalBehavior();
This compiles fine, but at runtime my code is failing in the attempted cast return (IAnimalService<AnimalSettings>) new CatService();, with an InvalidCastException.
How should I be casting my more derived type to a less derived type so that callers can use that interfaced base type to invoke functionality?
Changing the cast to (IAnimalservice<CatSettings>) new CatService() does work, but it's intended that the caller receives a IAnimalservice<AnimalSettings> so that it can handle any sort of animal (In other words, the caller should not be using any of the more specialized types). Should I be specifying an in or out as part of the generic definition somewhere?
By giving a complete example it would be much easier to help. ;-)
So here is the working code. And as Sweeper already mentioned, you need to add the out parameter at the interface to make it work.
using System;
public class Program
{
public static void Main()
{
var catService = new CatService(new CatSettings());
var genericService = (IAnimalService<AnimalSettings>)catService;
genericService.DoAnimalBehavior();
}
}
public abstract class AnimalSettings
{
public abstract void DoAnimalBehavior();
}
public class CatSettings : AnimalSettings
{
public override void DoAnimalBehavior()
{
Console.WriteLine("Meeoh");
}
}
public interface IAnimalService<out TSettings>
{
void DoAnimalBehavior();
}
public abstract class AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings
{
private readonly TSettings _settings;
public AnimalService(TSettings settings)
{
_settings = settings;
}
public void DoAnimalBehavior()
{
_settings.DoAnimalBehavior();
}
}
public class CatService : AnimalService<CatSettings>
{
private readonly CatSettings _catSettings;
public CatService(CatSettings catSettings)
: base(catSettings)
{
_catSettings = catSettings;
}
}
I have a little difficulty to explain the problem clearly in words so i'll start with the code immediately:
public interface ITemplate
{
bool DoSomething(string a);
}
public class Worker
{
public void DoSomeWork(ITemplate subcontractor)
{
try {
//Do some work...
if(subcontractor.DoSomething("hello"))
{
//Do some more work
}
}
catch(InvalidOperationException) {/*...*/}
//catch(Exception2) {/*...*/}
//catch(Exception3) {/*...*/}
//catch(Exception4) {/*...*/}
}
}
public class BaseClass : ITemplate
{
public void myFunction1()
{
Worker worker = new Worker();
worker.DoSomeWork(this);
}
public bool DoSomething(string a)
{
//Some code here
return true;
}
}
public class DerivedClass : BaseClass, ITemplate
{
public void myFunction2()
{
Worker worker = new Worker();
worker.DoSomeWork(this);
}
public bool DoSomething(string a)
{
//Some other code here
return true;
}
}
With this structure, if i call myDerivedClass.myFunction1(), the worker.DoSomeWork() function will execute DerivedClass.DoSomething(), but i want BaseClass.DoSomething() to be executed in that context, how can i do ?
Maybe it is not possible to achieve what i'm trying to do in that context with the template method design pattern.
The initial problem was that i need a method to execute code, but some part of this code is code is variable according on what object called the method.
Is there another way to do that without if(typeOf(subcontractor) == ...) which is not a very good practice, i would like the variable part of the code to be stored and executed inside the caller object.
Could i pass a delegate or something in the parameter instead of sending the whole caller object ?? i'm not very used to work with delegate/etc but i think it might be helpful for my problem, am i right ?
thanks
Jonathan
That is the correct behavior and is how polymorphism works. If you have an instance of the derived class DerivedClass and you have overridden a method, say DoSomething, then all calls to the method DoSomething in the code of the base class will go through the overridden method in the derived class if dealing with an instance of the derived type.
If you wish the code in the base class to be executed, then you need to either not override the method, or call the base class method from the derived class:
public class BaseClass
{
public virtual void MyMethod()
{
// Do some stuff...
}
}
public class DerivedClass : BaseClass
{
public override void MyMethod()
{
// Do something new...
// Do the stuff in BaseClass.MyMethod()
base.MyMethod();
}
}
DerivedClass is an ITemplate since it inherits from BaseClass which is an ITemplate. You don't need DerivedClass to directly implement ITemplate.
Also, as said above, the code you posted won't compile.
public interface ITemplate
{
bool DoSomething(string a);
}
public class Worker
{
public void DoSomeWork(ITemplate subcontractor)
{
//Do some work...
if(subcontractor.DoSomething("hello"))
{
//Do some more work
}
}
}
public BaseClass : ITemplate
{
public void myFunction1()
{
Worker worker = new Worker();
worker.DoSomeWork(this);
}
public bool DoSomething(string a)
{
//Some code here
}
}
public DerivedClass : BaseClass
{
public void myFunction2()
{
Worker worker = new Worker();
worker.DoSomeWork(this);
}
}
Is it possible to inherit constructors, and if so, how?
I am trying to make a class that inherits a System class, and I want the constructors of it.
This is not possible in vanilla C#. Constructors can't be simply inheritted. They must be redefined on every level and then chained to the parent's version.
class Parent {
internal Parent(string str) { ... }
internal Parent(int i) { ... }
}
class Child : Parent {
internal Child(string str) : base(str) { ... }
internal Child(int i) : base(i) { ... }
}
Constructors don't 'inherit' the same way that methods do, but you do have the option of invoking base class constructors:
public DerivedClass(Foo foo) : base(foo)
All the other answers so far are correct. However, understand that you do not have to match the base class constructor's signature with the constructor you are defining:
public class Base
{
public Base(string theString) { ... }
}
public class Derived:Base
{
public Derived():base("defaultValue") //perfectly valid
{ ... }
public Derived(string theString)
:base(theString)
{ ... }
public Derived(string theString, Other otherInstance)
:base(theString) //also perfectly valid
{ ... }
}
... and in addition to invoking a parent class's constructor, you can also "overload" constructors within the same inheritance level, by using the this keyword:
public class FurtherDerived:Derived
{
public FurtherDerived(string theString, Other otherInstance)
:base(theString, otherInstance)
{ ... }
public FurtherDerived()
:this("defaultValue", new Other()) //invokes the above constructor
{ ... }
}
You can't inherit constructors; you have to call them explicitly (except for the default constructor, which is called, well, by default):
class A
{
public A (int i) { }
}
class B : A
{
public B (int i) : base (i) { }
}
Let's say I have 2 constructors.
public class MyClass
{
public MyClass()
{
int id = 0;
//Same behaviour
}
Public MyClass(int id)
{
//Same behaviour
}
}
Both constructions implement the same behavior. The only difference is that, if the first constructor is called and the value of id = 0;
My question is to know if I can call the second constructor, instead of implemetanting the same behavior? If that's possible, do I do it?
You can do this:
public class MyClass {
public MyClass() : this(0) {
}
public MyClass(int id) {
}
}
Here's Microsoft's documentation on it. (you have to scroll down a bit; try searching for : this)
public class MyClass
{
public MyClass() : this(0)
{
}
public MyClass(int id)
{
//Same behaviour
}
}
Yes, this is called constructor chaining. It's achieved like so:
public class MyClass {
public MyClass() : this(0) { }
public MyClass(int id) {
this.id = id;
}
}
Note that you can chain to the base-class constructor like so:
public class MyClass : MyBaseClass {
public MyClass() : this(0) { }
public MyClass(int id) : base(id) { }
}
public class MyBaseClass {
public MyBaseClass(int id) {
this.id = id;
}
}
If there is a base class and you don't specify a constructor to chain to, the default is the accessible parameterless constructor, if there is one. If you do not specify a constructor to chain to and there is no accessible parameterless constructor, you will get a compile-time error.
If this is C# 4, an alternative is to use a default value for the constructor parameter (effectively making it optional):
public MyClass(int id = 0) { ...
I think this is the ideal solution for your example.
But it depends on whether you'd like to use this class as a type argument for a type parameter with a constructor constraint...
Why not put this same behavior in a private function?
Why is the following C# not legal? Does there exist a proper workaround?
public class Base
{
public Base(Func<double> func) { }
}
public class Derived : Base
{
public Derived() : base(() => Method()) <-- compiler: Cannot access non-static method 'Method' in static context
{
}
public double Method() { return 1.0; }
}
It's effectively referring to "this" within the arguments to the base constructor, which you can't do.
If your delegate really doesn't need access to this (which your sample doesn't) you can just make it static. You could also use a method group conversion to make it simpler:
public class Base
{
public Base(Func<double> func)
{
double result = func();
}
}
public class Derived : Base
{
public Derived() : base(Method)
{
}
public static double Method() { return 1.0; }
}
If you do need to use "this", you could:
Make it a virtual method instead of calling a delegate
Make it a static method which takes an appropriate instance, e.g.
public class Base
{
public Base(Func<Base, double> func)
{
double result = func(this);
}
}
public class Derived : Base
{
public Derived() : base(x => Method(x))
{
}
private static double Method(Base b)
{
// The documentation would state that the method would only be called
// from Base using "this" as the first argument
Derived d = (Derived) b;
}
}
Basically you get the compiler error because you are referencing the instance-method Method without an instance of your class Derived. When calling base, the constructor has not yet finished and you don't have an instance of your class yet. If you made Method static it would work just fine.
Another solution to this is simply to defer the initialization of the delegate to the derived class:
public class Base {
protected Func<double> DoubleFunc { get; set; }
protected Base() {
// defer initialization by not setting DoubleFunc
// or another possibility is to set it to a dummy function:
DoubleFunc = () => 0;
}
public Base(Func<double> func) {
DoubleFunc = func;
}
}
public class Derived : Base {
public Derived() {
DoubleFunc = Method;
}
public double Method() { return 1.0; }
}
Have you tried making Method() static as the compiler indicates? The problem is that an instance of Derived isn't available until after the constructor has returned so you can't call an instance method on it.
The "workaround" would be to make Method() a static method.
I can't explain the technical reasons why this does not work but essentially you're trying to call a method on an instance which does not yet exist. How could it possibly work?