Does covariance in different FWs cause code violation?

I saw a lecture by John Skeet at NDC 2010

He mentioned something interesting:

public Class Base { public void Foo(IEnumerable<string> strings){} } public Class Child:Base { publc void Foo(IEnumerable<object> objects) {} } Main : List<string> lst = new List<string>(); lst.Add("aaa"); Child c = new Child(); c.Foo(lst); 

From C # 3 it will call: Base.Foo

From C # 4 it will call: Child.Foo

I know this because covariance

Question:

Isn't that a code violation? Is there any workaround to keep this code working like it was in ver 3?

+4
source share
2 answers

Yes, this is an amazing change. Every time you make an invalid conversion legal, it is a violation.

Unfortunately, it is very difficult to add functions to the language without any changes. There are several more events in C # 4 if you really want to find them. This is unlikely to affect most developers, of course.

Similar violations were changed between C # 1 and C # 2, where the implementation used would change between different versions for this code:

 using System; public delegate void StringAction(string x); public class Base { public void Foo(string x) { Console.WriteLine("Base"); } } public class Child : Base { public void Foo(object x) { Console.WriteLine("Child"); } } public class Test { static void Main() { Child c = new Child(); StringAction action = new StringAction(c.Foo); action("x"); } } 

In this case, the compiler does issue a warning:

 Test.cs(26,31): warning CS1707: Delegate 'StringAction' bound to 'Child.Foo(object)' instead of 'Base.Foo(string)' because of new language rules 
+7
source

John, of course, is right; this is an amazing change. An even simpler way to see this violation:

 object x = new List<string>(); if (x is IEnumerable<object>) Console.WriteLine(4); else Console.WriteLine(3); 

In C # 3, which prints 3; in C # 4, it prints 4.

When you change the type system, you change the results of overload resolution; this is exactly how this happens. The advantage of this feature outweighs the pain of possible interruptions.

Is there a workaround? Yes. Do not call Child.Foo in the first place:

 Base c = new Child(); c.Foo(list); 
+5
source

Source: https://habr.com/ru/post/1397107/


All Articles