Принцип подстановки Лискова Инвариантность [закрыто]

Может ли кто-нибудь объяснить мне, почему этот код не работает? Как это связано с правилом LSP? Что в этом контексте означает инвариантность?

Пример взят из Адаптивного кода из книги C #:

      class Program
{
    static void Main(string[] args)
    {
        IDictionary<A, A> dict1 = new Dictionary<B,B>();
        IDictionary<B,B> dict2 = new Dictionary<A, A>();    
    }
}
public class A { }
public class B: A { }

Сообщение об ошибке

Ошибка CS0266 Невозможно неявно преобразовать тип System.Collections.Generic.Dictionary<LSP.core.B, LSP.core.B> в System.Collections.Generic.IDictionary<LSP.core.A, LSP.core.A>'. Существует явное преобразование (отсутствует ли приведение?)
Ошибка CS0266 Невозможно неявно преобразовать тип System.Collections.Generic.Dictionary<LSP.core.A, LSP.core.A> в System.Collections.Generic.IDictionary<LSP.core.B, LSP.core.B>'. Существует явное преобразование (вам не хватает приведения?)

2 ответа

Простой пример:

      class A { }
class B : A { }
class C : A { }

// Imagine this was allowed:
var dict1 = new Dictionary<B, B>();
IDictionary<A, A> dict2 = dict1;

// Then you did this:
var c = new C();
dict2[c] = c;

// And finally tried to do this:
B b = dict1.Keys.First(); // Breaks type safety, because First() returns a C instance

Это потому, что IDictionary - это generic класс.

Возьмем следующий пример:

      public class A { }
public class B: A { }

B является подклассом A, поэтому это разрешено.

      A varName = new B();

но когда вы используете varName в коде вы можете получить доступ только к свойствам класса A

Но List<B> не является подклассом List<A>, Несмотря на то Bявляется подклассом.
Компилятор не проверяет тип универсального параметра на наследование и считает их разными типами.

следующее не допускается

      List<A> listName = new List<B>();

какой идентификатор разрешен для использования правила LSP для заполнения списка

      List<A> listName = new List<A>();
ListName.Add(new B());

Но когда вы получаете доступ ListName[0] компилятор рассматривает полученный объект как тип A объект.

Другие вопросы по тегам