里氏代换原则不变性
The Liskov substitution principle Invariance
任何人都可以向我解释为什么这段代码不起作用吗?与 LSP 规则有何关系?在这种情况下,不变性是什么意思?
示例来自 Adaptive code via 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 { }
错误信息
Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.Dictionary<LSP.core.B, LSP.core.B>' to 'System.Collections.Generic.IDictionary<LSP.core.A, LSP.core.A>'. An explicit conversion exists (are you missing a cast?)
Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.Dictionary<LSP.core.A, LSP.core.A>' to 'System.Collections.Generic.IDictionary<LSP.core.B, LSP.core.B>'. An explicit conversion exists (are you missing a cast?)
一个简单的例子:
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
class.
举个例子:
public class A { }
public class B: A { }
B 是 A 的子class,所以这是允许的。
A varName = new B();
但是当您在代码中使用 varName
时,您只能访问 A class
的属性
但是 List<B>
不是 List<A>
的子class,即使 B
是 A
的子class。
编译器不检查继承的泛型参数类型,并认为它们是不同的类型。
不允许以下内容
List<A> listName = new List<B>();
允许什么id使用LSP规则来填充列表
List<A> listName = new List<A>();
ListName.Add(new B());
但是当您访问 ListName[0]
时,编译器会将您将获得的对象视为类型 A
对象。
任何人都可以向我解释为什么这段代码不起作用吗?与 LSP 规则有何关系?在这种情况下,不变性是什么意思?
示例来自 Adaptive code via 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 { }
错误信息
Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.Dictionary<LSP.core.B, LSP.core.B>' to 'System.Collections.Generic.IDictionary<LSP.core.A, LSP.core.A>'. An explicit conversion exists (are you missing a cast?)
Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.Dictionary<LSP.core.A, LSP.core.A>' to 'System.Collections.Generic.IDictionary<LSP.core.B, LSP.core.B>'. An explicit conversion exists (are you missing a cast?)
一个简单的例子:
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
class.
举个例子:
public class A { }
public class B: A { }
B 是 A 的子class,所以这是允许的。
A varName = new B();
但是当您在代码中使用 varName
时,您只能访问 A class
但是 List<B>
不是 List<A>
的子class,即使 B
是 A
的子class。
编译器不检查继承的泛型参数类型,并认为它们是不同的类型。
不允许以下内容
List<A> listName = new List<B>();
允许什么id使用LSP规则来填充列表
List<A> listName = new List<A>();
ListName.Add(new B());
但是当您访问 ListName[0]
时,编译器会将您将获得的对象视为类型 A
对象。