Понимание IEnumerable - логика IEnumerator - PullRequest
3 голосов
/ 27 февраля 2020

Я застрял с книгой Адама Фримена "Asp net", я много читал об IEnumerable и интерфейсе IEnumerator, но некоторые результаты все еще трудно понять. У меня есть эти два класса.

public class ShoppingCart : IEnumerable<Product>
{
    public IEnumerable<Product> Products { get; set; }

    public IEnumerator<Product> GetEnumerator()
    {
        return Products.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

и расширение первого,

 public static class MyExtensionMethods
{
    public static decimal TotalPrices (this IEnumerable<Product> products)
    {
        decimal total = 0;
        foreach (Product prod in products)
        {
            total += prod?.Price ?? 0;
        }
        return total;
    }
}

Product - это простой класс с некоторыми полями, такими как Name, Price et c. У меня много сомнений. Прежде всего, я не понимаю, как c# знает, что MyExtensionMethods является расширением ShoppingCart, затем я не понимаю, как TotalPrices может узнать, что продукт происходит из продуктов в классе ShoppingCart. Может ли кто-нибудь кратко объяснить мне логику c за этими несколькими строчками?

Спасибо всем, извините за тупой вопрос.

1 Ответ

3 голосов
/ 27 февраля 2020

Прежде всего, я не понимаю, откуда c# знает, что MyExtensionMethods является расширением ShoppingCart

это не ; "magi c" здесь - это this IEnumerable<Product> products, который говорит, что "метод является методом расширения для всего, что является IEnumerable<Product>" - и поскольку ShoppingCart удовлетворяет этому, он работает.

тогда я не понимаю, как TotalPrices может узнать, что продукт взят из продуктов в классе ShoppingCart

Он не не имеет доступа Products на ShoppintCart; проходит через GetEnumerator(); это работает, потому что foreach (Product prod in products) может работать (среди прочего) с чем-то, что IEnumerable<Product> - что мы знаем products, потому что так оно определено. В основном это становится:

    public static decimal TotalPrices (this IEnumerable<Product> products)
    {
        decimal total = 0;
        using (var iter = products.GetEnumerator())
        {
            while (iter.MoveNext())
            {
                var prod = iter.Current;
                total += prod?.Price ?? 0;
            }
        }
        return total;
    }

, который определяется через IEnumerable<T>. Хорошая новость: вам обычно никогда не нужно это знать - просто знайте, что foreach работает с последовательностями, а IEnumerable<T> является последовательностью T.

...