c# - foreach 如何将对象转换为指定类型?

标签 c# foreach ienumerable

我对 C# 中的 foreach 行为有疑问。

我的自定义类实现自定义 GetEnumerator。此方法返回另一个可隐式转换为 stringobject

但是,如果我执行 foreach(customClass 中的 string s),它会在运行时失败(“无法将 .. 类型的对象转换为字符串”)。

但是,如果我执行 string x = new B(),它就像一个魅力。

注意:这里没有什么特别需要实现的,我只是想了解发生了什么。我对这种-通用行为特别感兴趣。

有什么想法吗?我缺少哪些基础知识?

复制这个的代码:

public class A : IEnumerable
{
    #region IEnumerable Members

    public IEnumerator GetEnumerator()
    {
        yield return new B();
    }

    #endregion
}

public class B
{
    public static implicit operator string( B b )
    {
        return "to-stringed implicit";
    }
}

// CODE:

A a = new A();

// Works.
B b = new B();
string xxx = b;

// Doesnt work.
foreach( string str in a )
{
}

最佳答案

您的隐式转换只能在编译器认为它可以在编译时使用时使用:

B b = new B();
string str = b;

它不能在运行时使用:

B b = new B();
object obj = b;
string str = obj; // will fail at run-time

基本上,这是因为查看所有 obj 的可能转换成本太高了到 string那可能有用。 (参见 this Eric Lippert blog post)。


你的 IEnumerator返回对象,所以调用 foreach (string str in a)正在尝试转换 objectB在运行时。

var e = a.GetEnumerator();
e.MoveNext();
object o = e.Current;
string str = o; // will fail at run-time

如果您改为使用 foreach(B item in a) { string str = item; ... } ,运行时转换来自 objectB (有效,因为每个对象一个 B ),以及从 B 的转换至 str可以由编译器生成。

var e = a.GetEnumerator();
e.MoveNext();
object o = e.Current;
B item = o;        // will work at run-time because o _is_ a B
string str = item; // conversion made by the compiler

解决这个问题的另一种方法是制作 A实现 IEnumerable<B>而不仅仅是 IEnumerable .然后,foreach (string str in a)多译为

var e = a.GetEnumerator();
e.MoveNext();
B b = e.Current; // not object!
string str = b;  // conversion made by the compiler

因此编译器可以进行转换而无需更改 foreach循环。

关于c# - foreach 如何将对象转换为指定类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14630700/

相关文章:

r - 如何在多线程遍历迭代之前和之后减少 foreach 花费的时间?

c# - 如何正确使用 InsertAllOnSubmit() 是否比循环 InsertOnSubmit() 更好?

c# - 删除 FileSystemWatcher 正在监视的文件夹

c# - 如何按名称选择 Sqlparameter 列表元素?

php - 如何将foreach循环生成的变量传递给PHP中的另一个页面

php - 在 mysql select foreach 之后更新行

c# - 如何在另一台计算机上运行包含本地 SQL Server 数据库的 C# 应用程序?

c# - Ninject 绑定(bind) 101

c# - 为什么 DbSet<t>.Where() 默认使用 IQueryable 版本?

c# - 如何使用其键从 IEnumerable 集合中获取值?