问题描述
谁能向我解释为什么这段代码不起作用?与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
错误 CS0266 无法将类型“System.Collections.Generic.Dictionary
解决方法
一个简单的例子:
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 是一个 f x = Suc x
类。
举个例子:
generic
B 是 A 的子类,所以这是允许的。
public class A { }
public class B: A { }
但是当您在代码中使用 A varName = new B();
时,您只能访问 A 类的属性
但是 varName
不是 List<B>
的子类,即使 List<A>
是 B
的子类。
编译器不会检查继承的泛型参数类型,而是将它们视为不同的类型。
以下是不允许的
A
允许id使用LSP规则填充列表
List<A> listName = new List<B>();
但是当您访问 List<A> listName = new List<A>();
ListName.Add(new B());
时,编译器会将您获得的对象视为类型 ListName[0]
对象。