Created
October 15, 2020 17:02
-
-
Save popcatalin81/02a0da921d6752f97a3239f1d6dde2a3 to your computer and use it in GitHub Desktop.
My Linqpad ultils
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Extensions class with enumerable extensions targeted at code generation | |
/// </summary> | |
public static class EnumerableExtensions | |
{ | |
/// <summary> | |
/// Yields a single value | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="instance"></param> | |
/// <returns></returns> | |
public static IEnumerable<T> Yield<T>(T instance) | |
{ | |
yield return instance; | |
} | |
/// <summary> | |
/// Yields two values | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="instance1"></param> | |
/// <param name="instance2"></param> | |
/// <returns></returns> | |
public static IEnumerable<T> Yield<T>(T instance1, T instance2) | |
{ | |
yield return instance1; | |
yield return instance2; | |
} | |
/// <summary> | |
/// Yields tree values | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="instance1"></param> | |
/// <param name="instance2"></param> | |
/// <param name="instance3"></param> | |
/// <returns></returns> | |
public static IEnumerable<T> Yield<T>(T instance1, T instance2, T instance3) | |
{ | |
yield return instance1; | |
yield return instance2; | |
yield return instance3; | |
} | |
/// <summary> | |
/// Batches the source enumerable into a sequence of enumerable each containing <para>size</para> elements at most | |
/// </summary> | |
/// <typeparam name="T">Element Type</typeparam> | |
/// <param name="source">The source <see cref="IEnumerable{T}"/></param> | |
/// <param name="size">Size of the batch indicating the maximum number of elements in each batch sequence</param> | |
/// <returns></returns> | |
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size) | |
{ | |
if (size < 1) throw new ArgumentOutOfRangeException(nameof(size)); | |
var enumerator = source.GetEnumerator(); | |
IEnumerable<T> BatchCounter(int curentCount) | |
{ | |
do | |
{ | |
yield return enumerator.Current; | |
} while (--curentCount > 0 && enumerator.MoveNext()); | |
} | |
while (enumerator.MoveNext()) | |
{ | |
yield return BatchCounter(size); | |
} | |
} | |
/// <summary> | |
/// Returns a wrapped enumerable that contains info for each enumerated item, | |
/// like the index in original source, and whether it's first or last element in the original source | |
/// </summary> | |
/// <typeparam name="T">the type of elements in sequence</typeparam> | |
/// <param name="source">the source</param> | |
/// <returns>wrapped enumerable sequence</returns> | |
public static IEnumerable<ItemInfo<T>> WithInfo<T>(this IEnumerable<T> source) | |
{ | |
if (source == null) | |
throw new ArgumentNullException(nameof(source)); | |
IEnumerable<ItemInfo<T>> WithInfoIterator() | |
{ | |
using (var enumerator = source.GetEnumerator()) | |
{ | |
int index = 0; | |
if (!enumerator.MoveNext()) | |
yield break; | |
T current = enumerator.Current; | |
if (enumerator.MoveNext()) | |
{ | |
yield return new ItemInfo<T>(true, false, index++, current); | |
current = enumerator.Current; | |
} | |
else | |
{ | |
yield return new ItemInfo<T>(true, true, index, current); | |
yield break; | |
} | |
while (enumerator.MoveNext()) | |
{ | |
var next = enumerator.Current; | |
yield return new ItemInfo<T>(false, false, index++, current); | |
current = next; | |
} | |
yield return new ItemInfo<T>(false, true, index, current); | |
} | |
} | |
return WithInfoIterator(); | |
} | |
/// <summary> | |
/// Recreates the info for an enumerable sequence | |
/// </summary> | |
/// <typeparam name="T">the type of elements in sequence</typeparam> | |
/// <param name="source">the source</param> | |
/// <returns>wrapped enumerable sequence</returns> | |
public static IEnumerable<ItemInfo<T>> WithInfo<T>(this IEnumerable<ItemInfo<T>> source) | |
{ | |
return WithInfo(source.Select(s => s.Item)); | |
} | |
/// <summary> | |
/// Memoizes the enumerable | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="source"></ | |
public static IEnumerable<T> Memoize<T>(this IEnumerable<T> source) | |
{ | |
if (source == null) throw new ArgumentNullException(nameof(source)); | |
List<T> cache = new List<T>(); | |
bool cacheComplete = false; | |
IEnumerable<T> Cached() | |
{ | |
if (cacheComplete) | |
{ | |
foreach (var element in cache) | |
{ | |
yield return element; | |
} | |
} | |
else | |
{ | |
foreach (var element in source) | |
{ | |
cache.Add(element); | |
yield return element; | |
} | |
cacheComplete = true; | |
} | |
} | |
return Cached(); | |
} | |
} | |
public struct ItemInfo<T> | |
{ | |
[Flags] | |
private enum Info | |
{ | |
None = 0, | |
IsFirst, | |
IsLast | |
} | |
internal ItemInfo(bool first, bool last, int index, T item) | |
{ | |
info = (first ? Info.IsFirst : 0) | (last ? Info.IsLast : 0); | |
Index = index; | |
Item = item; | |
} | |
private readonly Info info; | |
public bool IsFirst => info.HasFlag(Info.IsFirst); | |
public bool IsLast => info.HasFlag(Info.IsLast); | |
public readonly int Index; | |
public readonly T Item; | |
} | |
/// <summary> | |
/// Extensions class with Array extensions targeted at working with tuples and deconstruction | |
/// </summary> | |
public static class ArrayExtensions | |
{ | |
public static void Deconstruct<T>(this IList<T> list, out T first) | |
{ | |
first = Ge(list, 0); | |
} | |
public static void Deconstruct<T>(this IList<T> list, out T first, out T second) | |
{ | |
first = Ge(list, 0); | |
second = Ge(list, 1); | |
} | |
public static void Deconstruct<T>(this IList<T> list, out T first, out T second, out T third) | |
{ | |
first = Ge(list, 0); | |
second = Ge(list, 1); | |
third = Ge(list, 2); | |
} | |
public static void Deconstruct<T>(this IList<T> list, out T first, out T second, out T third, out T forth) | |
{ | |
first = Ge(list, 0); | |
second = Ge(list, 1); | |
third = Ge(list, 2); | |
forth = Ge(list, 3); | |
} | |
public static void Deconstruct<T>(this IList<T> list, out T first, out T second, out T third, out T forth, out T fifth) | |
{ | |
first = Ge(list, 0); | |
second = Ge(list, 1); | |
third = Ge(list, 2); | |
forth = Ge(list, 3); | |
fifth = Ge(list, 4); | |
} | |
public static void Deconstruct<T>(this IList<T> list, out T first, out T second, out T third, out T forth, out T fifth, out T sixth) | |
{ | |
first = Ge(list, 0); | |
second = Ge(list, 1); | |
third = Ge(list, 2); | |
forth = Ge(list, 3); | |
fifth = Ge(list, 4); | |
sixth = Ge(list, 5); | |
} | |
public static void Deconstruct<T>(this IList<T> list, out T first, out T second, out T third, out T forth, out T fifth, out T sixth, out T seventh) | |
{ | |
first = Ge(list, 0); | |
second = Ge(list, 1); | |
third = Ge(list, 2); | |
forth = Ge(list, 3); | |
fifth = Ge(list, 4); | |
sixth = Ge(list, 5); | |
seventh = Ge(list, 6); | |
} | |
public static void Deconstruct<T>(this IList<T> list, out T first, out T second, out T third, out T forth, out T fifth, out T sixth, out T seventh, out T eigth) | |
{ | |
first = Ge(list, 0); | |
second = Ge(list, 1); | |
third = Ge(list, 2); | |
forth = Ge(list, 3); | |
fifth = Ge(list, 4); | |
sixth = Ge(list, 5); | |
seventh = Ge(list, 6); | |
eigth = Ge(list, 7); | |
} | |
private static T Ge<T>(IList<T> list, int index) | |
{ | |
if (index < list.Count) | |
return list[index]; | |
return default(T); | |
} | |
} | |
public static class StringBuilderExtensions | |
{ | |
public static IndentedStringBuilder Indented(this StringBuilder sb, int identSize = 4, char identChar = ' ') | |
{ | |
return new IndentedStringBuilder(sb, identSize, identChar); | |
} | |
} | |
public class IndentedStringBuilder | |
{ | |
private readonly StringBuilder sb; | |
private int ident = 0; | |
private int identSize = 0; | |
private bool newLine = false; | |
private char identChar; | |
internal IndentedStringBuilder(StringBuilder sb, int identSize = 4, char identChar = ' ') | |
{ | |
this.sb = sb; | |
this.identSize = identSize; | |
this.identChar = identChar; | |
} | |
/// <summary> | |
/// Write line to string builder with current indent | |
/// </summary> | |
public IndentedStringBuilder W(string line = "") | |
{ | |
Write(line); | |
return this; | |
} | |
/// <summary> | |
/// Write line to string builder and increase ident | |
/// </summary> | |
public IndentedStringBuilder WI(string line = "") | |
{ | |
Write(line); | |
ident++; | |
return this; | |
} | |
/// <summary> | |
/// Increase ident and write line to string builder | |
/// </summary> | |
public IndentedStringBuilder IW(string line = "") | |
{ | |
ident++; | |
Write(line); | |
return this; | |
} | |
/// <summary> | |
/// Write line to string builder and decrease ident | |
/// </summary> | |
public IndentedStringBuilder WD(string line = "") | |
{ | |
Write(line); | |
ident--; | |
return this; | |
} | |
/// <summary> | |
/// Decrease ident and write line to string builder | |
/// </summary> | |
public IndentedStringBuilder DW(string line = "") | |
{ | |
ident--; | |
Write(line); | |
return this; | |
} | |
/// <summary> | |
/// Append to current line | |
/// </summary> | |
public IndentedStringBuilder Append(string value = "") | |
{ | |
sb.Append(value); | |
return this; | |
} | |
/// <summary> | |
/// Append to current line | |
/// </summary> | |
public IndentedStringBuilder Each<T>(IEnumerable<T> values, Action<IndentedStringBuilder, ItemInfo<T>> action) | |
{ | |
foreach (var value in values.WithInfo()) | |
{ | |
action(this, value); | |
} | |
return this; | |
} | |
/// <summary> | |
/// Chain another builder action to this instance | |
/// </summary> | |
public IndentedStringBuilder Do(Action<IndentedStringBuilder> action) | |
{ | |
action(this); | |
return this; | |
} | |
/// <summary> | |
/// Chain another builder action to this instance | |
/// </summary> | |
public IndentedStringBuilder Do<T>(Action<IndentedStringBuilder, T> action, T item) | |
{ | |
action(this, item); | |
return this; | |
} | |
private void Write(string line) | |
{ | |
if (newLine) | |
sb.AppendLine(); | |
else | |
newLine = true; | |
if (string.IsNullOrEmpty(line)) | |
return; | |
sb.Append(identChar, ident * identSize); | |
sb.Append(line); | |
} | |
public override string ToString() | |
{ | |
return sb.ToString(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment