Здравствуйте, btn1, Вы писали:
B>Здравствуйте, artelk, Вы писали:
A>>Развлекался тут на досуге A>>public static class Listuple
B>А теперь можно написать класс Zvezduple! Пример использования:
B>
B>var star = new Zvezduple(mnogo_babla);
B>star.push(fabrika_zvezdei());
B>star.Pop(Lena_Terleeva);
B>
B>Зачем оно надо — ну... примерно затем же, что и Листупле.
Не, Zvezduple так просто не получить, тем более чтоб объект Lena_Terleeva в Pop.
Здравствуйте, Spiceman, Вы писали:
S>Здравствуйте, artelk, Вы писали:
A>>Когда оно может быть полезным пока не придумал.
S>Какую задачу хоть решал?
Ну, в общем, захотелось сдалать такой Tuple, который можно представить в виде коллекции (неизменяемый односвязный список), к которому можно добавить элемент (причем любого типа), удалять элемент (голову списка), пройтить по элементам и применить некую (параметрически) полиморфную функцию (Invoke<T> в IListupleVisitor). И чтоб все статически типизировано.
В дотнете есть класс ObjectResult<T>, реализующий IEnumerable<T> и у которого есть метод GetNextResult<TElement>(), возвращающий ObjectResult<TElement>.
Т.е. тут подразумевается цепочка вызовов, выгребающая объекты разных типов. Возможно где-то еще есть что-то подобное.
Если реализовать для моего Listuple какие-то алгоритмы, то их можно будет использовать для ObjectResult<T> (и для других подобных классов) путем написания несложных обвязок и хэлперов.
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, artelk, Вы писали:
_NN>Обычный неизменяемый односвязный список.
Не так чтоб совсем обычный. Add конструирует новый тип, заворачивая исходный. _NN>А 'Tuple' тут при чем ?
По сути это Tuple — упорядоченный набор разнотипных значений со статической проверкой типов. Просто создается он путем последовательного добавления элементов в обратном порядке. И вместо, например, Item2 (или функции snd) нужно писать list.Tail.Head и т.п.
Здравствуйте, artelk, Вы писали:
_NN>>Обычный неизменяемый односвязный список. A>Не так чтоб совсем обычный. Add конструирует новый тип, заворачивая исходный.
Не приметил гетерогенность списка. _NN>>А 'Tuple' тут при чем ? A>По сути это Tuple — упорядоченный набор разнотипных значений со статической проверкой типов. Просто создается он путем последовательного добавления элементов в обратном порядке. И вместо, например, Item2 (или функции snd) нужно писать list.Tail.Head и т.п.
Вместо L<H, T> можно было бы нагенерировать несколько классов вида L<T0> .. L<T0...Tn>
Тогда доступ был бы всегда через Item(n) , а Add реализовать так:
class L<T0>
{
L<T0, T1> Add(T1 t1) { return new L<T0, T1>(Item0, t1); }
}
...
// Ну и создание можно упростить как бы:static class ListTuple
{
public static L<T0> Create(T0 t0) { return L<T0>(t0); }
...
public static L<T0..Tn> Create(T0 t0...Tn tn) { return L<T0..Tn>(t0..tn); }
}
Здравствуйте, _NN_, Вы писали:
_NN>Вместо L<H, T> можно было бы нагенерировать несколько классов вида L<T0> .. L<T0...Tn>
Да. Только тогда они повторяли бы уже существующие Tuple<T0...Tn>, лучше уж использовать сразу их.
_NN>Тогда доступ был бы всегда через Item(n) , а Add реализовать так: _NN>
_NN>class L<T0>
_NN>{
_NN> L<T0, T1> Add(T1 t1) { return new L<T0, T1>(Item0, t1); }
_NN>}
_NN>...
_NN>// Ну и создание можно упростить как бы:
_NN>static class ListTuple
_NN>{
_NN> public static L<T0> Create(T0 t0) { return L<T0>(t0); }
_NN>...
_NN> public static L<T0..Tn> Create(T0 t0...Tn tn) { return L<T0..Tn>(t0..tn); }
_NN>}
_NN>
Create у туплов уже есть, методы Add можно нагенерить для всех вариантов их "длин". А еще нужно нагенерить методы GetTail() для обратной декомпозиции. А еще нагенерить Apply...
Здравствуйте, artelk, Вы писали:
A>Create у туплов уже есть, методы Add можно нагенерить для всех вариантов их "длин". А еще нужно нагенерить методы GetTail() для обратной декомпозиции. А еще нагенерить Apply...
И оформить в NuGet .
Ну так делов-то, скрипт на питоне пишется за минуту.
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, artelk, Вы писали:
A>>Create у туплов уже есть, методы Add можно нагенерить для всех вариантов их "длин". А еще нужно нагенерить методы GetTail() для обратной декомпозиции. А еще нагенерить Apply...
_NN>И оформить в NuGet . _NN>Ну так делов-то, скрипт на питоне пишется за минуту.
Вот смотри, допустим мы захотели подружить Listuple с ObjectResult<T>:
public static class ObjectResultListupleExtensions
{
public static Fetcher<T, Nil> Fetch<T>(this ObjectResult<T> objectResult)
{
return new Fetcher<T, Nil>(objectResult, Nil.Value);
}
public struct Fetcher<T, TTail>
where TTail : L
{
private readonly ObjectResult<T> objectResult;
public readonly L<IReadOnlyList<T>, TTail> Result;
public Fetcher(ObjectResult<T> objectResult, TTail tail)
{
this.objectResult = objectResult;
Result = tail.Add(objectResult.ToList());
}
public Fetcher<TNext, L<IReadOnlyList<T>, TTail>> Next<TNext>()
{
return new Fetcher<TNext, L<IReadOnlyList<T>, TTail>>(objectResult.GetNextResult<TNext>(), Result);
}
}
}
Для туплов пришлось бы генерить методы Next. И вообще на каждый чих пришлось бы генерить пачку методов для всех возможных туплов. А все потому, что для туплов на уровне системы типов нельзя выразить "тупл, полученный путем добавления такого-то значения к такому-то туплу".
Хотя нагенерить методы Create, GetItemN() и еще FromTuple/ToTuple было бы полезно — что-то удобней выражается через туплы, а что-то — через вот такой вот Listuple.
Здравствуйте, artelk, Вы писали:
A>Использование:
Не, это абсолютно нереалистичный сценарий. Никто не будет мучаться с полу-типизацией (типы есть, семантической нагрузки нет), когда есть более простые и удобные решения. Обычно или используют POCO (тем более что их можно создать по использованию за секунду), или анонимные типы, или, на крайний случай, передают дальше датасет.
Так что я пожалуй присоединюсь к Spiceman: что-то я не вижу, где такую штуку можно использовать
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, artelk, Вы писали:
A>>Использование: S>Не, это абсолютно нереалистичный сценарий. Никто не будет мучаться с полу-типизацией (типы есть, семантической нагрузки нет), когда есть более простые и удобные решения. Обычно или используют POCO (тем более что их можно создать по использованию за секунду), или анонимные типы, или, на крайний случай, передают дальше датасет.
ObjectResult — оно про хранимки, возвращающие множественные резалтсеты. POCO как раз используются (я в примере примитивные типы поставил, каюсь; там как раз POCO должны стоять).
S>Так что я пожалуй присоединюсь к Spiceman: что-то я не вижу, где такую штуку можно использовать
В батчевых запросах можно еще использовать — набиваешь батч запросами (IQueryable), выполняешь и получаешь Listuple с результатами.
Здравствуйте, artelk, Вы писали:
A>ObjectResult — оно про хранимки, возвращающие множественные резалтсеты.
Ну, это всё-таки очень частный случай.
Я бы не вытаскивал информацию о порядке запросов за пределы DAL и ограничился бы стандартным подходом.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, artelk, Вы писали:
A>>ObjectResult — оно про хранимки, возвращающие множественные резалтсеты. S>Ну, это всё-таки очень частный случай. S>Я бы не вытаскивал информацию о порядке запросов за пределы DAL и ограничился бы стандартным подходом.
А я не настаиваю на вытаскивании этой информации из DAL.
Код по ссылке:
private static CategoriesProducts GetAllCategriesAndProducts()
{
CategoriesProducts categProd = new CategoriesProducts();
categProd.Categories = new List<Category_SprocResult>();
categProd.Products = new List<Product_SprocResult>();
using (var dbContext = new StoreDBEntities())
{
var results = dbContext.GetAllCategorisAndProducts();
//Get first enumerate result set
categProd.Categories.AddRange(results);
//Get second result setvar products = results.GetNextResult<Product_SprocResult>();
categProd.Products.AddRange(products);
//Return all result setsreturn categProd;
}
}
У results и products тип как раз ObjectResult<T>. Почему ты противопоставляешь "стандартный подход" моему?
В моем случае было бы как-то так:
private static CategoriesProducts GetAllCategriesAndProducts()
{
using (var dbContext = new StoreDBEntities())
{
var results = dbContext.GetAllCategorisAndProducts()
.Fetch<Category_SprocResult>()
.Next<Product_SprocResult>
.Result
.ToTuple();
return new CategoriesProducts { Categories = results.Item1, Products = results.Item2 };
}
}
Порядок типов при выгребании данных важен. С моим подходом он виден лучше.
Клиенту уйдёт готовый список.
A>Порядок типов при выгребании данных важен. С моим подходом он виден лучше.
Только типы другие. И обычно код закладывается на последовательность "прочитали всё, затем вызвали GetNextResult()". Твой вариант может упасть с сторонними провайдерами.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, artelk, Вы писали:
A>>У results и products тип как раз ObjectResult<T>. Почему ты противопоставляешь "стандартный подход" моему? S>
Ничо не понял. У меня там будет IReadOnlyList<T> вместо List<T>. К этому претензия?
A>>Порядок типов при выгребании данных важен. С моим подходом он виден лучше. S>Только типы другие. И обычно код закладывается на последовательность "прочитали всё, затем вызвали GetNextResult()". Твой вариант может упасть с сторонними провайдерами.
Конструктор Fetcher сразу делает objectResult.ToList(), все так же будет выполнятся.