【问题标题】:C# cast from IEnumerable<T> to TC# 从 IEnumerable<T> 强制转换为 T
【发布时间】:2020-05-07 13:03:13
【问题描述】:

谁能解释一下:

  • 编译成功
  • 运行时 KO

我已经检查了 IEnumerable 和 IEnumerable 的源代码,但一无所获 仅供参考,这不适用于列表

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;
    }
}

【问题讨论】:

  • List&lt;Person&gt;IEnumerable&lt;Person&gt; 是人员的集合。 Person 是一个人。你不能把一群人变成一个人。
  • 此外,即使可能,如代码中所写,列表也不包含元素。哪一个会收到 Age 属性的值 5?
  • IEnumerable&lt;Person&gt; list零个或多个项的集合。如果你想要一个单个项目,你应该指定哪一个,例如list.First().Age = 5;如果要修改集合中的所有项目,则必须循环:foreach (var item in list) item.Age = 5;
  • @sofienereghima 演员表是运行时断言。您向编译器承诺 listPerson 通过进行强制转换,即使编译器认为它知道不同。然后编译器关闭并编译您的代码,而在运行时失败。

标签: c# ienumerable implicit-conversion explicit-conversion


【解决方案1】:

我尝试了一些对 C# 编译器和运行时来说不太有用但“正确”的方法

我得到了答案

    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

【讨论】:

  • 这仍然不是一个很好的例子。对于一个简单的节点类来说相当复杂并且不可扩展并且需要装箱。
  • 不要发布代码图片。发布代码本身。
  • 不知道为什么您要尝试使用一种构造来枚举集合的元素来表示元素的单个实例。也许您已经找到了一种方法来使编译器静音并且不会获得运行时错误,但是这种用法在逻辑级别上是错误的。您正在尝试将特定工具用于不同的工作,例如使用锤子杀死蚊子。使用这些工具来实现它们的目的。
  • @canton7 我想提一下调试时的值,这就是我导入图像的原因
  • @sofienereghima 也发布代码。这些是规则,它们的存在是有原因的。
【解决方案2】:

在编译时没有检查接口转换为类。

如您所见,您甚至可以编译它:

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; }
}

转换为类的接口将在运行时进行评估。

事实上,如果你使用Pizza&lt;Pasta&gt;而不是IPizza&lt;Pasta&gt;,它会给你一个编译错误:

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; }
}

【讨论】:

  • salemo System.InvalidCastException: '无法将'Pizza`1[Pasta]'类型的对象转换为'Pasta'类型。我需要一个具体的用途请
  • 你根本做不到。没有正确的用法。我解释了你为什么。
  • 如果 Pasta 实现 IPizza,你可以做到(你的第一个例子)但我想知道这有什么用处......
  • 你不懂。即使编译了,在运行时也是无效的,你做不到。
  • 成功了 :) 检查我的答案,有一个链接的图像。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多