2010-08-07 3 views
2

Это, безусловно, не нарушает стандартную практику .NET framework. Когда я вижу a + b, я всегда предполагаю, что будет создано что-то новое.Имеет ли неизменяемый список, который перегружает «+»?

static void Main(string[] args) 
{ 
    var list = BuildList(ImmutableList<int>.Empty); 
    var sum = (list + 500).Sum(); 
    Console.WriteLine(sum); 
    Console.ReadLine(); 
} 

static ImmutableList<int> BuildList(ImmutableList<int> list) 
{ 
    if (list.Count < 1000) 
    { 
     return BuildList(list + list.Count); 
    } 
    return list; 
} 

Update

после знакомства Джон Скит на то, что в name methods on immutable lists.

Неожиданные Ответы

Я очень удивлен, что так много ответов, которые согласны, что это имеет смысл. В принципе, я тоже согласен, но мне легче читать вербальный код, чем тот, кому неудобно с трудом читать, хорошо сложенный код. Из моего опыта работы они кажутся большинством.

+0

Зачем вам это нужно? –

+1

Несомненно, это, в основном, понимание списка a la Haskell. В этом нет ничего плохого. –

ответ

6

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

Перегрузка оператора имеет смысл, если у вас есть небольшой неизменяемый класс или структура, которая должна вести себя как «примитивный» тип. Однако, когда вы начинаете пытаться сделать это для других классов, это действительно влияет на ремонтопригодность.

Я бы рекомендовал вместо этого использовать явные вызовы методов.


После прочтения комментариев, моя рекомендация будет использовать Concat() (в соответствии Enumerable.Concat в Framework). Другой вариант я бы предпочел бы Construct(), ала cons (хотя против обычно предваряется), чтобы сделать использование очень ясно:

var list = BuildList(ImmutableList<int>.Empty); 
var list2 = list.Concat(500); 
// Or: var list2 = list.Construct(500); 
+0

Это «структура», которая никак не может быть мутирована, поэтому по существу она ведет себя точно так же, как «int». – ChaosPandion

+0

@ChaosPandion: Нет, это действительно не так. Он неизменен, как int, но концептуально отличается. Коллекция концептуально не примитивный объект. –

+1

@ChaosPandion: Я не говорю, что вы ~ не можете этого сделать - просто я чувствую, что это добавляет что-то очень непонятное в ваш API и, вероятно, значительно уменьшит ремонтопригодность и понятность вашего кода. –

2

Что + означает в этом контексте? Мне кажется непонятным (без чтения кода). IList + IList Я мог видеть, может быть, оператор объединения или комбинирование списков (сохранение дубликатов) или любое другое. IList + int меня просто смущает. Мне кажется, что метод с ясным именем сделает гораздо более читаемый код, чем оператор, которому придется искать или комментировать каждый раз, когда вы используете перегруженный оператор.

+0

Что бы вы назвали этим методом? – ChaosPandion

+0

Предполагая, что это добавляет элемен t в список, ссылка, которую вы предоставили на пост Джона Скита, является хорошим ресурсом. Я лично, вероятно, брошу свою шляпу в качестве голоса за '.Cons()' или '.Добавить() '- помимо изменчивости, это делает то же самое, что и. .Add()' в 'List'. – PeterL

+0

Я нахожусь на заборе между 'Cons' и' Concat'. – ChaosPandion

2

Одна вещь об операторах заключается в том, что люди ожидают, что они будут относительно эффективными. Нечего сказать, что это должно быть, но люди, похоже, ожидают этого.

Если внутренне структура такого списка позволила вам создать объединенный список, указав, что он хранит ссылки на два источника, из которых он был получен (вполне возможно, особенно учитывая, что неизменяемость сводит на нет риск запутывания побочных эффектов) то я бы пошел на это. Если бы это было возможно сделать относительно дорогостоящую операцию, я бы этого не сделал. «concatenate()« может заставить кого-то подумать «действительно ли мне нужно переместить эту большую память вокруг здесь, в этом замкнутом цикле, в котором я сейчас, или я должен рассмотреть другой подход» в то время, когда такая мысль подходит.

+0

Я выполнил некоторые тесты производительности, и моя реализация на удивление хороша с результатами, подобными «string». Очевидно, не так хорошо, но похоже. – ChaosPandion

+0

Хотя «знайте, что + медленнее со строками» часто является одной из первых вещей, рассказанных новичкам, именно потому, что они могут предполагать обратное (а затем он становится завышенным до такой степени, чтобы избежать его, но это другое дело). На такой скорости, я думаю, я бы опереться, но я не думаю, что это неправильно, если кто-то сделает это. –

+0

В тех случаях, когда вам нужна жесткая петля. Я бы сказал, что используйте измененный список, но сохраняйте его в пределах одной функции. – ChaosPandion

5

Неизменный список символов, который перегружает + имеет смысл; мы называем их строками. По аналогии, вы можете сказать, что неизменный список всего, что перегружает оператора + для вызова операции Concat, имеет смысл.

Кстати, я недавно создал аналогичную функцию, что вы описываете:

public static IEnumerable<T> Append<T>(this IEnumerable<T> list, T item) 
{ 
    foreach (T i in list) 
     yield return i; 
    yield return item; 
} 

Я решил, что Append добавляет один элемент в списке, в то время как Concat добавляет целый список в конец списка ,

+1

+1 - Вы знаете, что это то, о чем я думал, но путаница, которая, по-видимому, заставляет людей действительно перевешивать краткость ее использования. Теперь я никогда не использовал бы это за пределами своих личных проектов, тогда я бы, вероятно, использовал его, но я хочу использовать его и на своей работе. * (Меня так тошнит от проблем, вызвав нулевых изменяемых списков.) * – ChaosPandion

+0

Может быть, я не смущен, потому что Python использует '+' для конкатенации списков, но я не помню, чтобы меня путали, когда я впервые увидел его. Какие люди путают «список + список»? – Gabe

+1

потому что некоторые люди не * думаю *. – Joshua

1

Я бы это сделал.

В конце концов, строка представляет собой список символов.

И да, если бы я увидел < список > + < список > я сразу думаю, что конкатенация (единственной возможностью является векторной суммой, и это редко).