Свойство типа IAsyncEnumerable - рекомендации
От: Shmj Ниоткуда  
Дата: 17.11.21 14:15
Оценка:
Такой вопрос.

Когда метод возвращает IAsyncEnumerable — это как бы привычно.

А как на счет свойства IAsyncEnumerable? По-моему не встречал. Какие рекомендации по этому поводу?

Нужно ли добавлять суффикс Async в именовании? Нет ли подводных камней?

Если объект Disposable, то как бы есть риск забыть об этом и при передаче значения свойства в другой метод — объект, которому оно принадлежит — уже будет того. Однако же можно применить IAsyncDisposable — тогда, вроде, так не ошибешься.

Кто что скажет?
Re: Свойство типа IAsyncEnumerable - рекомендации
От: Ночной Смотрящий Россия  
Дата: 17.11.21 15:00
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Если объект Disposable, то как бы есть риск забыть об этом и при передаче значения свойства в другой метод — объект, которому оно принадлежит — уже будет того. Однако же можно применить IAsyncDisposable — тогда, вроде, так не ошибешься.


Ты путаешь. IDisposable наледуется IAsyncEnumerator, а не IAsyncEnumerable.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: Свойство типа IAsyncEnumerable - рекомендации
От: Shmj Ниоткуда  
Дата: 17.11.21 15:26
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Ты путаешь. IDisposable наледуется IAsyncEnumerator, а не IAsyncEnumerable.


Вот код для демонстрации проблемы, дабы не многословить:

  Скрытый текст
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ConsoleApp39
{
    class Program
    {
        public class C1 : IDisposable
        {
            private bool _isDisposed;

            private List<string> _list = new()
            {
                "1", "2", "3"
            };

            public IAsyncEnumerable<string> Items => GetAsyncEnumerable();

            private async IAsyncEnumerable<string> GetAsyncEnumerable()
            {
                foreach (var item in _list)
                {
                    if (_isDisposed)
                        throw new ObjectDisposedException("");

                    await Task.Delay(100);

                    yield return item;
                }
            }

            public void Dispose()
            {
                _isDisposed = true;
            }
        }

        static async Task Main(string[] args)
        {
            var items = GetItems();

            await foreach (var item in items)
            {
                Console.WriteLine(item);
            }
        }

        static IAsyncEnumerable<string> GetItems()
        {
            using C1 c1 = new C1();
            return c1.Items;
        }
    }
}


Если C1 сделать IAsyncDisposable — то проблема исчезает:

  Скрытый текст
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ConsoleApp39
{
    class Program
    {
        public class C1 : IAsyncDisposable
        {
            private bool _isDisposed;

            private List<string> _list = new()
            {
                "1", "2", "3"
            };

            public IAsyncEnumerable<string> Items => GetAsyncEnumerable();

            private async IAsyncEnumerable<string> GetAsyncEnumerable()
            {
                foreach (var item in _list)
                {
                    if (_isDisposed)
                        throw new ObjectDisposedException("");

                    await Task.Delay(100);

                    yield return item;
                }
            }
            
            public async ValueTask DisposeAsync()
            {
                _isDisposed = true;
            }
        }

        static async Task Main(string[] args)
        {
            var items = GetItems();

            await foreach (var item in items)
            {
                Console.WriteLine(item);
            }
        }

        static async IAsyncEnumerable<string> GetItems()
        {
            await using C1 c1 = new C1();

            await foreach (var item in c1.Items)
            {
                yield return item;
            }
        }
    }
}
Отредактировано 17.11.2021 15:35 Shmj . Предыдущая версия .
Re: Свойство типа IAsyncEnumerable - рекомендации
От: karbofos42 Россия  
Дата: 17.11.21 15:54
Оценка: 3 (1) +2
Здравствуйте, Shmj, Вы писали:

S>Кто что скажет?


Вне зависимости от контекста, свойство, которое генерирует новые объекты и выполняет сложные, объёмные операции — это зло.

Свойства провоцируют не записывать значение в локальную переменную, а постоянно его дёргать, тем самым создавая новые объекты.
В итоге будет либо просто жор памяти и процессора, либо нестыковка данных.
Re: Свойство типа IAsyncEnumerable - рекомендации
От: Sinclair Россия http://corp.ingrammicro.com/Solutions/Cloud.aspx
Дата: 17.11.21 16:05
Оценка: 3 (1)
Здравствуйте, Shmj, Вы писали:
S>Когда метод возвращает IAsyncEnumerable — это как бы привычно.
S>А как на счет свойства IAsyncEnumerable? По-моему не встречал. Какие рекомендации по этому поводу?
Пока что вообще IAsyncEnumerable не шибко часто встречается. Сходу не вижу никаких особенных причин любить IAsyncEnumerable свойства меньше, чем IEnumerable.
В обоих случаях мы возвращаем не "копию значения", а некоторый promise, который надо будет опрашивать в будущем.
S>Нужно ли добавлять суффикс Async в именовании? Нет ли подводных камней?
Если у вас есть оба варианта свойства, то, естественно, нужно добавлять суффикс Async. А если у вас вообще весь код асинхронный, то можно и так обойтись.
S>Если объект Disposable, то как бы есть риск забыть об этом и при передаче значения свойства в другой метод — объект, которому оно принадлежит — уже будет того. Однако же можно применить IAsyncDisposable — тогда, вроде, так не ошибешься.
S>Кто что скажет?
Корень проблем с Disposable не имеет никакого отношения к async:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ConsoleApp39
{
    class Program
    {
        public class C1 : IDisposable
        {
            private bool _isDisposed;

            private List<string> _list = new()
            {
                "1", "2", "3"
            };

            public IEnumerable<string> Items => GetEnumerable();

            private  IEnumerable<string> GetEnumerable()
            {
                foreach (var item in _list)
                {
                    if (_isDisposed)
                        throw new ObjectDisposedException("");
                    yield return item;
                }
            }

            public void Dispose()
            {
                _isDisposed = true;
            }
        }

        static void Main(string[] args)
        {
            var items = GetItems();

            foreach (var item in items)
                Console.WriteLine(item);
        }

        static IEnumerable<string> GetItems()
        {
            using C1 c1 = new C1();
            return c1.Items;
        }
    }
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
http://rsdn.org/File/5743/rsdnaddict.GIF
Re[2]: Свойство типа IAsyncEnumerable - рекомендации
От: Shmj Ниоткуда  
Дата: 17.11.21 16:12
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Пока что вообще IAsyncEnumerable не шибко часто встречается. Сходу не вижу никаких особенных причин любить IAsyncEnumerable свойства меньше, чем IEnumerable.


Под IEnumerable часто скрывается статический List, просто делают для универсальности. Т.е. такие свойства никаких ресурсоёмких операций не выполняют. А вот IAsyncEnumerable как бы намекает, что будет выполнена сложная и длительная операция, отдавать результат будет порциями.
Re[3]: Свойство типа IAsyncEnumerable - рекомендации
От: karbofos42 Россия  
Дата: 17.11.21 16:50
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, Sinclair, Вы писали:


S>>Пока что вообще IAsyncEnumerable не шибко часто встречается. Сходу не вижу никаких особенных причин любить IAsyncEnumerable свойства меньше, чем IEnumerable.


S>Под IEnumerable часто скрывается статический List, просто делают для универсальности. Т.е. такие свойства никаких ресурсоёмких операций не выполняют. А вот IAsyncEnumerable как бы намекает, что будет выполнена сложная и длительная операция, отдавать результат будет порциями.


Тут же принципиальной разницы нет. Сам объект, реализующий интерфейс IAsyncEnumerable может собираться быстрее, чем IEnumerable. Интерфейс и интерфейс.
Сложная и длительная операция будет уже в дальнейшем вызове GetAsyncEnumerator и в работе с Enumerator'ом.
В тот же List завтра могут завезти реализацию IAsyncEnumerable, чтобы было.
Re[4]: Свойство типа IAsyncEnumerable - рекомендации
От: Shmj Ниоткуда  
Дата: 17.11.21 17:45
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>Тут же принципиальной разницы нет. Сам объект, реализующий интерфейс IAsyncEnumerable может собираться быстрее, чем IEnumerable. Интерфейс и интерфейс.


Свойства рекомендуют делать легкими — просто вернул/установил значение, дернул типа дернул Notify (или что-то лекое) — и все. Без сложных операций — в таких случаях рекомендуют метод с префиксом Get.

Если свойство IEnumerable — то, вероятнее всего, это обертка над полем типа List или Collection. Т.е. никакая работа не проводится — просто результат. Выбирают IEnumerable для максимального абстрагирования — типа вдруг захотим переделать внутреннюю реализацию. Хотя это спорный момент, конечно.

А IAsyncEnumerable сам по себе подразумевает, что будет делать некий длительный запрос или же некую работу и отдавать результат по частям, чтобы ты мог обрабатывать отдельные части сразу а не дожидаться полного списка.

Так что, наверное, не стоит.
Отредактировано 17.11.2021 17:46 Shmj . Предыдущая версия .
Re[3]: Свойство типа IAsyncEnumerable - рекомендации
От: Ночной Смотрящий Россия  
Дата: 17.11.21 18:02
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Вот код для демонстрации проблемы, дабы не многословить:


То что C# позволяет выстрелить себе в ногу — не проблема. И это вообще никак не связано с IAsyncEnumerable.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: Свойство типа IAsyncEnumerable - рекомендации
От: Sinclair Россия http://corp.ingrammicro.com/Solutions/Cloud.aspx
Дата: 18.11.21 01:25
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Под IEnumerable часто скрывается статический List, просто делают для универсальности. Т.е. такие свойства никаких ресурсоёмких операций не выполняют. А вот IAsyncEnumerable как бы намекает, что будет выполнена сложная и длительная операция, отдавать результат будет порциями.

Согласен. В целом, наверное, лучше отдавать такое методом. Уже потом, глядя на код, должно быть понятно — есть ли смысл заменить метод свойством с точки зрения читаемости кода.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
http://rsdn.org/File/5743/rsdnaddict.GIF
Re: Свойство типа IAsyncEnumerable - рекомендации
От: vaa https://www.youtube.com/playlist?list=PLtrvASfI1KW7VOYRKjglcagQzWLoxlncl
Дата: 18.11.21 02:28
Оценка: +2
Здравствуйте, Shmj, Вы писали:

S>Такой вопрос.


S>Когда метод возвращает IAsyncEnumerable — это как бы привычно.


S>А как на счет свойства IAsyncEnumerable? По-моему не встречал. Какие рекомендации по этому поводу?


Есть общее правило(даже вроде на мсдн было): если выполняются длительные вычисления то метод, если просто отдается ссылка или значение достаточно {get;}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.