Почему конструктор с параметром интерфейса используется вместо конструктора с наиболее производным типом параметра? - PullRequest
0 голосов
/ 08 февраля 2019

Я столкнулся с проблемой в нашем коде, когда некоторая информация исчезала.Я нашел решение для этого, но я не совсем понимаю это поведение.Для простоты я привел пример:

Общий интерфейс

public interface IFruit
{
    Color Color { get; set; }
}

2 производных класса:

public class Apple : IFruit
{
    public int Radius { get; set; }
    public Color Color { get; set; }

    public Apple(IFruit fruit)
    {
        Color = fruit.Color;
    }

    public Apple(Apple apple)
    {
        Color = apple.Color;
        Radius = apple.Radius;
    }

    public Apple(Color color, int radius)
    {
        Color = color;
        Radius = radius;
    }

    public override string ToString()
    {
        return $"I'm a {Color.ToString()} apple with a radius of {Radius}cm";
    }
}

public class Banana : IFruit
{
    public int Length { get; set; }
    public Color Color { get; set; }

    public Banana(IFruit fruit)
    {
        Color = fruit.Color;

    }

    public Banana(Banana banana)
    {
        Color = banana.Color;
        Length = banana.Length;
    }

    public Banana(Color color, int lenght)
    {
        Color = color;
        Length = Length;
    }


    public override string ToString()
    {
        return $"I'm a {Color.ToString()} banana with a length of {Length}cm";
    }
}

Тестовый код:

[TestClass]
public class FruitTests
{
    [TestMethod]
    public void WhichConstructorIsUsed()
    {
        var fruits = new List<IFruit>();
        fruits.Add(new Apple(Colors.Red, 5));
        fruits.Add(new Banana(Colors.Yellow, 20));

        var clonedFruits = fruits.Select(f => new Apple(f));

        Console.WriteLine(string.Join("\n", clonedFruits));
    }
}

Выход

Я Красное яблоко с радиусом0 см

Я - Желтое яблоко с радиусом 0 см

Что я не понимаю

Обратите внимание, что красное яблокотеряет значение радиусаЯ понимаю, что банан теряет информацию, но я не понимаю, почему, например, для Apple вместо конструктора Apple (Apple apple) используется конструктор Apple (фрукт Apple).Это яблоко, оно просто в типизированном списке базового типа.

Я ожидал, что экземпляр Banana будет использовать более общий конструктор, но не экземпляр Apple.

1 Ответ

0 голосов
/ 08 февраля 2019

В момент, когда вы извлекаете f из списка, он имеет тип IFruit, поскольку вы объявили свой список как List<IFruit>.Когда вы вызываете f => new Apple(f), вы вызываете конструктор Apples с IFruit, а не с конкретным типом.

Если бы вы явным образом отлили Apple из списка, вы получили бы полный доступ ко всем конкретнымТипы свойств.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...