c#iEnumerable< t> - 这是“标记接口”吗?

发布于 2025-01-26 08:10:42 字数 1010 浏览 4 评论 0原文

我意识到iEnumerable< t>在这个论坛上已经讨论了很多。

当您打电话给返回任何类型对象的iEnumerable的东西时,您并没有回到任何事物的具体实现。如果您在调试器中检查返回的数据(或在返回集合中调用getType()),则其类型简称为ienumerable< myclass>(除非我们当然实现了它通过调用tolist()toarray()等)。

我也很清楚,如果我们创建了一个实现iEnumerable< t>的类,我们必须自己实现getEnumerator()方法。

但是,框架/运行时如何在引擎盖下处理它?例如,即使在iEnumerable< int> numbers = enumerable.range(0,10),我们知道在执行链中的某个点上,正在创建getEnumerator()的具体实现并打电话给我们,即使我们自己没有自己实施这种方法。

Microsoft将其视为标记接口吗?换句话说 - 运行时是否在我们的代码中遇到/处理一种返回可恢复的方法后,是否将其视为元数据并创建/注入某种默认实现?

从技术上讲,标记界面是(可以说)代码的气味,因为根据OOP原则,界面应该是合同或模板,实际上不应 do 任何东西它)。

但是,在iEnumerable< t>的情况下,显然在封面下要做一些事情。如果您在上面的琐碎示例中检查了调试器中的数字变量,您将看到它包含必须已在某个地方实现的实际,具体,可呼叫的成员。

例如:如果您调用getEnumerator()在任何一个实例上某种例外(即,“嘿,我只是一个界面,我只是声明作为合同的一部分,我实际上不包含它的实现,我不知道如何处理”)。但是相反,它被成功地称为。

到底发生了什么?

I realize that IEnumerable<T> has been discussed quite a bit on this forum.

When you make a call to something that returns an IEnumerable of any type of object, you are not getting back a known concrete implementation of anything. If you inspect the returned data in your debugger (or calling GetType() on the returned collection), its type is simply IEnumerable<MyClass> (unless of course we materialize it by calling ToList(), ToArray() et al).

I am also well aware that if we are creating a class that implements IEnumerable<T>, we have to implement the GetEnumerator() method ourselves.

But how does the framework/runtime handle this under the hood? For example, even in a trivial case like IEnumerable<int> numbers = Enumerable.Range(0, 10), we know that at some point during the execution chain, a concrete implementation of GetEnumerator() is being created and called, even though we aren't implementing that method ourselves.

Is Microsoft treating this as a marker interface? In other words - does the runtime, upon encountering/processing a method in our code that returns an IEnumerable, treat it as metadata and create/inject some kind of default implementation?

Technically speaking, marker interfaces are (arguably) a code smell, since according to OOP principles an interface is supposed to be a mere contract or template and should not actually do anything (except enforce that contract upon classes implementing it).

But in the case of IEnumerable<T>, there are clearly some things being done under the covers. If you examine the numbers variable in a debugger in my trivial example above, you will see that it contains actual, concrete, callable members which must have been implemented somewhere.

For example: if you call GetEnumerator() on any instance of an IEnumerable, what should happen (if MS was adhering to the strict definition of the OOP concept of interfaces) is some kind of exception (i.e., "Hey, I'm just an interface, I just declare that method as part of the contract, I don't actually contain an implementation of it and I have no idea what to do with it"). But instead, it gets called successfully.

What is really going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

想念有你 2025-02-02 08:10:42

返回iEnumerable的东西实际上是返回实现该接口的类。

例如以您的示例(enumoser.range),这是源代码,

 public static IEnumerable<int> Range(int start, int count)
    {
        long max = ((long)start) + count - 1;
        if (count < 0 || max > int.MaxValue)
        {
            ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count);
        }
 
        if (count == 0)
        {
            return Empty<int>();
        }
 
        return new RangeIterator(start, count); <<<<=====
    }

请参见 https://source.dot.dot.net/#system.linq/system/linq/linq/lanq/range.cs.fda9d378095a6464646464646464

 private sealed partial class RangeIterator : Iterator<int>

没有

 internal abstract class Iterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource>

魔术,enumerable.range返回rangeIterator的实例,该实例实现iEnumerable&lt; t&gt;

接口的点是呼叫者''''除返回的对象是否实现界面后面的情况,需要了解界面背后发生的事情。因此,呼叫者可以调用接口方法知道他们将在

读取LINQ源的工作非常有用,请使用该源浏览器非常有用的 https://source.dot.net/

Something that returns an IEnumerable<T> is actually returning a class that implements that interface.

For instance take your example (Enumerable.Range), here is the source code

 public static IEnumerable<int> Range(int start, int count)
    {
        long max = ((long)start) + count - 1;
        if (count < 0 || max > int.MaxValue)
        {
            ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count);
        }
 
        if (count == 0)
        {
            return Empty<int>();
        }
 
        return new RangeIterator(start, count); <<<<=====
    }

see https://source.dot.net/#System.Linq/System/Linq/Range.cs,fda9d378095a6464

following RangeIterator declaration stack

 private sealed partial class RangeIterator : Iterator<int>

and

 internal abstract class Iterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource>

no magic, Enumerable.Range returns an instance of RangeIterator, which implements IEnumerable<T>

The point of interfaces is that the caller doesn't need to know anything about what's going on behind the interface, other than the returned object implements it. So the caller can call the interface methods knowing that they will work

reading the LINQ source is very informative, use that source browser its amazingly useful https://source.dot.net/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文