-8

Can anyone explain that :

  • compile OK
  • run-time KO

I already checked source code for IEnumerable<> & IEnumerable and found nothing FYI this doesn't work with List

class Program
{
    public class Person
    {
        public long Age { get; set; }
    }

    static void Main(string[] args)
    {
        IEnumerable<Person> list = new List<Person>();
        ((Person)list).Age = 5;
    }
}
  • 2
    [Check this out please](https://meta.stackoverflow.com/questions/303812/discourage-screenshots-of-code-and-or-errors) – nalka Jan 21 '20 at 12:54
  • 4
    A `List` and an `IEnumerable` are collections of people. A `Person` is a single person. You can't turn a collection of people into a single person. – canton7 Jan 21 '20 at 12:54
  • 1
    Also, even if possible, as written in the code, the list doesn't contain elements. Which one will receive the value 5 for the Age property? – Steve Jan 21 '20 at 12:55
  • 1
    `IEnumerable list` is a *collection* of *zero or more* items. If you want a *single item* you should specify *which one*, e.g. `list.First().Age = 5;` If you want to modify *all items* within the collection, you have to loop: `foreach (var item in list) item.Age = 5;` – Dmitry Bychenko Jan 21 '20 at 12:55
  • Sorry but no one has explained to me the fact that compilation is OK :) – sofiene reghima Jan 21 '20 at 12:59
  • 1
    @sofienereghima A cast is a runtime assertion. You're promising to the compiler that `list` is a `Person` by doing the cast, even through the compiler thinks it knows differently. So then compiler shuts up and compiles your code, which fails at runtime instead. – canton7 Jan 21 '20 at 13:00
  • @canton7 and why this works with IEnumerable<> and not List<> ? – sofiene reghima Jan 21 '20 at 13:04
  • @HenkHolterman wrong aswer, re-read my question please – sofiene reghima Jan 21 '20 at 13:05
  • 1
    @sofienereghima `List` is a concrete type. The compiler knows everything about it, and it knows everything about the `Person` type. Because C# doesn't have multiple inheritance, it knows that you cannot make a type which inherits from both `Person` and `List`. `IEnumerable` is however an interface, and the compiler knows that it's possible for someone to create a class which inherits from `Person` but implements `IEnumerable`. – canton7 Jan 21 '20 at 13:06
  • @DmitryBychenko wrong aswer, re-read my question please – sofiene reghima Jan 21 '20 at 13:06
  • 1
    @sofienereghima Your question is very unclear, so it's not surprising that people haven't realised what you're *trying* to ask – canton7 Jan 21 '20 at 13:07
  • 1
    Guys this question is pretty answerable, you closed it while i was giving her the answer she wanted. I'm voting to reopen it. – Marco Salerno Jan 21 '20 at 13:09
  • @sofienereghima Please [edit] your question to clarify that you're asking why casting `IEnumerable` to `Person` is allowed by the compiler, but casting `List` to `Person` is not – canton7 Jan 21 '20 at 13:18
  • @canton7 thanks, I got my answer, but it is pretty confusing. I think it is a .net issue when using Interfaces rather than a useful method in coding. I'm using C# for about 8 years and it is the first time I get this issue. canton7, holterman, Do you had a concrete use for a class T : IEnumerable – sofiene reghima Jan 21 '20 at 13:30
  • 1
    @sofienereghima SO is a Q&A site. Askers have the responsibility to write a good question, even if they got an answer. No, this is very much by design: if the compiler can prove that the cast will never succeed, it is allowed to raise an error. You can never write code which lets a cast from `List` to `Person` succeed, but you *can* write code which lets a cast from `IEnumerable` to `Person` succeed. – canton7 Jan 21 '20 at 13:39

2 Answers2

0

There isn't a check at compile time for interface cast to class.

As you can see you can even compile that:

class Program
{
    static void Main(string[] args)
    {
        IPizza<Pasta> ao = new Pizza<Pasta>();
        ((Pasta)ao).MyProperty = 10;
    }
}

public interface IPizza<T>
{

}

public class Pizza<T> : IPizza<T>
{

}

public class Pasta
{
    public int MyProperty { get; set; }
}

Interface casted to class will be evaluated in runtime.

Infact, if you use as type Pizza<Pasta> instead of IPizza<Pasta> it will give you a compile error:

class Program
{
    static void Main(string[] args)
    {
        Pizza<Pasta> ao = new Pizza<Pasta>();
        ((Pasta)ao).MyProperty = 10;
    }
}
public interface IPizza<T>
{

}

public class Pizza<T> : IPizza<T>
{

}

public class Pasta
{
    public int MyProperty { get; set; }
}
Marco Salerno
  • 5,131
  • 2
  • 12
  • 32
-2

I tried something not too useful but "correct" for both C# compiler & runtime

I got my answer

    public class Person
    {
        public long Age { get; set; }
    }

    static void Main(string[] args)
    {
        IEnumerable<Person> list;
        list = new Father();
        ((Father)list).Age = 5;
    }

    public class Father : Person, IEnumerable<Person>
    {
        public IEnumerator<Person> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }
}

Example

  • Still this is not a good example. Quite complicated for a simple node class and not extensible and require boxing. – Franck Jan 21 '20 at 13:22
  • Please **do not** post images of code. Post the code itself. – canton7 Jan 21 '20 at 13:41
  • Not sure why you are trying to use a construct thought to Enumerate elements of a collection to represent instead a single instance of an element. Perhaps you have found a way to silence the compiler and obtain no runtime errors, but this usage is faulty at the logical level. You are trying to use a specific tool for a different work, like using a hammer to kill a mosquito. Use the tools for what they are built for. – Steve Jan 21 '20 at 13:45
  • @canton7 I wanted to mention the value in debug time, that's why I imported an image – sofiene reghima Jan 21 '20 at 13:47
  • @sofienereghima Post the code as well. Those are the rules, and they're there for a reason. – canton7 Jan 21 '20 at 13:49
  • @Steve I didn't used it, its my colleague. I was confused why compiler accepted It and know I see why, but I'm not confortable with it... – sofiene reghima Jan 21 '20 at 13:51