-2

Assume I already have a duck. Given that the Duck is readonly and C# is GC'd, is there any way to drop a duck into a mallard with inheritance without hitting a copy constructor?

public class Duck
{
    public readonly int wings;
    public Duck(int w)
    {
        wings = w;
    }
}

public class Mallard : Duck
{
    public Mallard(Duck a) : base(a.wings)
    {
    }
}
maccettura
  • 10,514
  • 3
  • 28
  • 35
Carbon
  • 3,828
  • 3
  • 24
  • 51
  • 1
    You can't "promote" an instance of one type to an instance of a derived type. `Duck` probably should be abstract, anyway. – madreflection Oct 21 '19 at 19:33
  • "without hitting a copy constructor" You've only defined one constructor for the `Mallard` class. The only way to create a Mallard object is to run that constructor. – gunr2171 Oct 21 '19 at 19:33
  • make the parent data for mallard be a duck, but not create a new duck. – Carbon Oct 21 '19 at 19:33
  • 4
    `var duck = new Duck(3); duck = new Mallard(duck);` You really ought to specify which side the extra wing is on, though. That'll affect navigation. Also there's a chicken/egg issue. – 15ee8f99-57ff-4f92-890c-b56153 Oct 21 '19 at 19:34
  • 1
    "parent data" suggests composition. Now you're talking about the decorator pattern. But you can't avoid creating a new instance of *something*. – madreflection Oct 21 '19 at 19:37
  • I assume under the hood the base object is just a ref though? Can you point it to the other instantiated object given that the base object in this case can never change? – Carbon Oct 21 '19 at 19:38
  • what does "not create a new duck" mean? do you need to modify a certain instance of a Duck object to behave like a Mallard? https://stackoverflow.com/questions/7299097/dynamically-replace-the-contents-of-a-c-sharp-method – Tiberiu Maran Oct 21 '19 at 19:38
  • Are you trying to translate `static_cast(duck)` (C++) to C#? – madreflection Oct 21 '19 at 19:40
  • @madreflection Yeah – Carbon Oct 21 '19 at 19:40
  • It would be unsafe to assume that the memory layout of `Mallard` is the same as `Duck`, even if *you* don't add any fields or virtual overrides to `Mallard`, so it's not possible. – madreflection Oct 21 '19 at 19:42
  • @madreflection note that in C++ that's undefined behavior if `Duck` is not actually a `Mallard`, and even if you don't hit anything sensitive, the polymorphic behavior of the `Mallard` will still be as a `Duck`, because you're not changing the vtable of the instance – Tiberiu Maran Oct 21 '19 at 19:43
  • @artcorpse: I'm quite aware of that. It doesn't change the fact that *the OP* is trying to do it. – madreflection Oct 21 '19 at 19:44
  • 1
    @Carbon It might help to understand why you need such a static_cast, as it doesn't seem to accomplish much. If you need to operate with methods from type `Mallard` on a `Duck` something like this might work: https://blog.tchatzigiannakis.com/changing-an-objects-type-at-runtime-in-c-sharp/. – Tiberiu Maran Oct 21 '19 at 19:56
  • 1
    More importantly, will your design also need to convert the river to whiskey? – 15ee8f99-57ff-4f92-890c-b56153 Oct 21 '19 at 20:04

1 Answers1

2

A Duck is not a Mallard, and in C# there's no way to make it be one. You're going to have to construct a new Mallard in some way, whether that's by a copy constructor or other method.

In some cases, you may be able to go with composition over inheritance (although I don't think it models your domain in this example).

public class Mallard
{
   public readonly Duck duck;
   public Mallard(Duck d)
   {
      duck = d;
   }
}

If you're just looking to add new functionality to a Duck, but can't change it, you can use extension methods.

public static class DuckExtensions
{
   public IEnumerable<Wing> CookWings(this Duck duck) { ... }
}
Kyle W
  • 3,702
  • 20
  • 32