0

Is there a way to implement the following logic in C#? (note: the following code does not compile)

abstract class Foo {
    void Bar(Object obj);
}

class SubFoo<T> : Foo {
    override void Bar(T obj);
}

Notice how SubFoo overrides the Bar(..) method with a more specific parameter type.

товіаѕ
  • 2,881
  • 4
  • 23
  • 53
  • 1
    dynamic is its own thing, you cannot override it with a `T` – maccettura Jan 19 '18 at 17:46
  • 2
    Why not declare base class as generic instead of using dynamic? – Gilad Green Jan 19 '18 at 17:47
  • @maccettura @GiladGreen i changed it to `Object` .. since I don't know how to do it I'm still looking for the right way to achieve this – товіаѕ Jan 19 '18 at 17:50
  • @TobiasWürth you still didn't answer the question why would you override it that way ? – Left panda Jan 19 '18 at 17:51
  • 1
    You might want to read on the [Liskov Substitution Principle](https://stackoverflow.com/questions/56860/what-is-an-example-of-the-liskov-substitution-principle) – Camilo Terevinto Jan 19 '18 at 17:53
  • @Leftpanda imagine pipes you can connect building a pipelien with the following class declaration `Pipe` ... imagine the following pipeline `Pipe,TA>` <-> `Pipe` <-> `Pipe` .. how do you define the `Connect(Pipe)` method without limitting yourself but still having a typesafe declaration at compile time? – товіаѕ Jan 19 '18 at 18:07
  • @TobiasWürth there must be a common properties on the in and out as well you can create an interface and use it ? – Left panda Jan 19 '18 at 18:16
  • @Leftpanda no the idea is that you can build a pipeline and the pipeline can change the type. aka process the input. i guess there is no interface which would cover all different types and their combination in use – товіаѕ Jan 19 '18 at 18:18
  • @TobiasWürth and then why you don't want to make the base class generic ? – Left panda Jan 19 '18 at 18:21
  • @Leftpanda because I want to connect them (e.g. linked list) and by that want to have a non-generic, but plain class to be able to define lists like `List` .. doing this with generics would limit me by not allowing me to insert different types. e.g. `List>` would not work if I had a different pipe type I'd like to insert into this list – товіаѕ Jan 19 '18 at 18:23

2 Answers2

7

No you can't the override must have the same signature as the original. There are several alternatives:

Make the base class generic

abstract class Foo<TArg>
{
    public abstract void Bar(TArg obj);
}

class SubFoo<T> : Foo<T>
{
    public override void Bar(T obj) { }
}

Leave the original function and add an overload

abstract class Foo
{
    public abstract void Bar(object obj);
}

class SubFoo<T> : Foo
{
    public void Bar(T obj) { }
    public override void Bar(object obj) => this.Bar((T)obj);
}

Use an interface instead of an abstract class to hide the less specific overload

interface Foo
{
    void Bar(object obj);
}

class SubFoo<T> : Foo
{
    public void Bar(T obj) { }

    void Foo.Bar(object obj) => this.Bar((T)obj);
} 
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
2

No, you cannot do that. Imagine this code:

Foo myFoo = new SubFoo<string>();

myFoo is is a Foo which takes an object, but it is actually an implementation of SubFoo which takes a string. So what would you expect to happen when you call

myFoo.Bar(1);

Foo.Bar takes an object, so you can pass in an integer, but SubFoo expects a string not an integer. The world blows up.

Nick
  • 4,556
  • 3
  • 29
  • 53