Skip to content

Instantly share code, notes, and snippets.

@kdbanman
Created September 3, 2015 18:01
Show Gist options
  • Save kdbanman/34baea357f6e8203f285 to your computer and use it in GitHub Desktop.
Save kdbanman/34baea357f6e8203f285 to your computer and use it in GitHub Desktop.
// So you want to use anonymous interface implementations in C#? Does this lambda-based usage look ok?
// Ignore the fact that "list" and "projection" are undefined here, just note the lambdas that can close
// around any variables and procedures you want.
new AnonymousReadOnlyList<TOut>(
count: () => list.Count,
item: i => projection(list[i]),
iterator: list.AsEnumerable().Select(projection));
new AnonymousReadOnlyList<TOut>(
count: () => list.Count,
item: i => projection(list[i], i),
iterator: list.AsEnumerable().Select(projection));
new AnonymousReadOnlyList<T>(
count: () => list.Count,
item: i => list[list.Count - 1 - i]);
new AnonymousReadOnlyList<TOut>(
count: () => Math.Min(list1.Count, list2.Count),
item: i => projection(list1[i], list2[i]),
iterator: list1.AsEnumerable().Zip(list2, projection));
new AnonymousReadOnlyList<int>(
count: () => count,
item: i => i,
iterator: Enumerable.Range(0, count));
// ... and so on. This is how:
// 1. Define your interface.
public interface IReadOnlyList<out T> : IReadOnlyCollection<T> {
T this[int index] { get; }
}
// 2. Provide a single not-so-concrete implementation for all anonymous implementations to use.
// This also shows how to provide "default methods" - GetEnumerator() here.
public sealed class AnonymousReadOnlyList<T> : IReadOnlyList<T> {
private readonly Func<int> _count;
private readonly Func<int, T> _item;
private readonly IEnumerable<T> _iterator;
public AnonymousReadOnlyList(Func<int> count, Func<int, T> item, IEnumerable<T> iterator = null) {
if (count == null) throw new ArgumentNullException("count");
if (item == null) throw new ArgumentNullException("item");
this._count = count;
this._item = item;
this._iterator = iterator ?? DefaultIterator(count, item);
}
private static IEnumerable<T> DefaultIterator(Func<int> count, Func<int, T> item) {
var n = count();
for (var i = 0; i < n; i++)
yield return item(i);
}
public int Count {
get {
return _count();
}
}
public T this[int index] {
get {
return _item(index);
}
}
public IEnumerator<T> GetEnumerator() {
return _iterator.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
// 3. Now you can create anonymous implementations with lambdas like the ones at the beginning of this gist!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment