Vâng điều này chắc chắn sẽ không được hỗ trợ trong C# 4. Có một vấn đề cơ bản:
List<Giraffe> giraffes = new List<Giraffe>();
giraffes.Add(new Giraffe());
List<Animal> animals = giraffes;
animals.Add(new Lion()); // Aargh!
Giữ hươu cao cổ an toàn: chỉ cần nói không với đúng không an toàn.
Phiên bản mảng hoạt động vì mảng làm phương sai loại tham chiếu hỗ trợ, với kiểm tra thời gian thực hiện. Điểm của generics là cung cấp biên dịch thời gian loại an toàn.
Trong C# 4, sẽ có hỗ trợ cho an toàn phương sai chung, nhưng chỉ dành cho giao diện và đại biểu. Vì vậy, bạn sẽ có thể làm:
Func<string> stringFactory =() => "always return this string";
Func<object> objectFactory = stringFactory; // Safe, allowed in C# 4
Func<out T>
là hiệp biến trong T
vì T
chỉ được sử dụng ở một vị trí đầu ra. Hãy so sánh điều đó với Action<in T>
đó là contravariant trong T
vì T
chỉ được sử dụng ở một vị trí đầu vào đó, làm cho an toàn này:
Action<object> objectAction = x => Console.WriteLine(x.GetHashCode());
Action<string> stringAction = objectAction; // Safe, allowed in C# 4
IEnumerable<out T>
là hiệp biến là tốt, làm đúng điều này trong C# 4, như chỉ ra bởi những người khác:
IEnumerable<Animal> animals = new List<Giraffe>();
// Can't add a Lion to animals, as `IEnumerable<out T>` is a read-only interface.
Xét về làm việc xung quanh này trong tình huống của bạn trong C# 2, bạn cần phải duy trì một danh sách, hoặc bạn sẽ được hạnh phúc tạo ra một danh sách mới? Nếu được chấp nhận, List<T>.ConvertAll
là bạn của bạn.
+1 chỉ để thêm vào câu trả lời của Jon (không phải là anh ấy cần bất kỳ trợ giúp nào), theo ví dụ 'Func' to 'Func
Cảm ơn bạn đã chỉ ra vấn đề an toàn loại. Điều đó thực sự hữu ích. – AndiDog
Có gì sai với 'animals.Add (new Lion()); // Aargh! Nếu bạn có thể tạo một 'Sư tử' và sử dụng nó như là một 'Động vật', và nếu bạn đang sử dụng tất cả các phần tử trong' động vật' như 'Động vật', thì vấn đề là gì? – Jeff