В C #:
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] {e}).Concat(c)));
}
Использование:
var result = Combinations(new[] { 1, 2, 3, 4, 5 }, 3);
Результат:
123
124
125
134
135
145
234
235
245
345
С MemoryStream
это немного спорный вопрос - поскольку в конечном итоге вы обращаетесь к управляемому byte[]
(поэтому он все равно будет ждать рутинной сборки мусора). Но в общем случае, да: вы должны закрыть (лучше: Dispose()
через using
, чтобы он закрывался при исключении) поток по завершении работы, иначе вы можете не передать некоторые данные в базовое (неуправляемое) место назначения. И есть некоторые потоки, которые на самом деле не полностью "промываются" при Flush()
- им нужно быть Close()
d (в частности, потоки сжатия).
GC .Net очень ... ленивый. Тот факт, что упоминание было утеряно, не означает, что он сразу же выметается, разбивается и отправляется на свалку. По этой причине всегда полезно закрывать открытые ресурсы и удалять объекты, которые реализуют IDisposable.
Хорошей практикой является закрытие ваших потоков. Используйте оператор using
, и Dispose ()
будет вызываться, когда он выпадает из области видимости (или при возникновении исключения), что, в свою очередь, закроет ваш поток.
static string SerialiseObjectToBase64(object obj)
{
using (var mstream = new MemoryStream())
{
...
return Convert.ToBase64String(mstream.ToArray());
}
}
Закрытие потоков и утилизация объектов - это две разные вещи. Закрытие потоков очищает буфер записи и записывает все незаписанные данные в поток. При утилизации потока просто освобождается память, используемая переменной потока.