Обновленный код
Для исправления ошибки отфильтрованного Interminable
, следующий код обновляется и объединяется в оригинал:
public static bool IsInfinity(this IEnumerable x) {
var it=
x as Infinity??((Func<object>)(() => {
var info=x.GetType().GetField("source", bindingAttr);
return null!=info?info.GetValue(x):x;
}))();
return it is Infinity;
}
bindingAttr
объявляется константой.
-
Резюме
Я пытаюсь реализовать бесконечное перечислимое, но встречающееся что-то кажется нелогичным и временно заканчивается. Мне нужно какое-то направление для завершения кода, став семантическим, логичным и разумным дизайном.
-
Вся история
Я задал вопрос несколько часов назад:
Является бесконечным перечислимым все еще "перечислимым" ,
Это не может быть хорошей моделью реализации. То, что я пытаюсь сделать, реализует перечисляемый, чтобы представить бесконечность, логически и семантически (я думал..). Я бы поставил код на последнем из этих сообщений.
большая проблема - это просто для представления бесконечного перечислимого, но перечисление на нем на самом деле не имеет никакого смысла, поскольку нет никаких реальных элементов.
Итак, помимо предоставления фиктивных элементов для перечисления, есть четыре варианта, которые я могу себе представить, а три приводят к
StackOverflowException
.-
Бросьте
InvalidOperationException
, как только он будет перечислить.public IEnumerator<T> GetEnumerator() { for(var message="Attempted to enumerate an infinite enumerable"; ; ) throw new InvalidOperationException(message); }
-
и 3. технически эквивалентны, пусть переполнение стека происходит при переполнении действительно.
public IEnumerator<T> GetEnumerator() { foreach(var x in this) yield return x; }
public IEnumerator<T> GetEnumerator() { return this.GetEnumerator(); }
-
(описано в 2)
-
Не ждите, когда это произойдет, просто бросьте
StackOverflowException
.public IEnumerator<T> GetEnumerator() { throw new StackOverflowException("... "); }
-
Сложные вещи:
Если применяется option 1
, то есть перечислять на этом перечислимом, становится недопустимой операцией. Разве не странно говорить, что эта лампа не используется для освещения (хотя это верно в моем случае).
Если применяется option 2
или option 3
, то есть мы планировали переполнение стека. Действительно ли это как название, только когда stackoverflow является справедливым и разумным? Совершенно логично и разумно?
Последний выбор option 4
. Тем не менее, стек фактически не переполняется, поскольку мы предотвратили его, выбросив поддельный StackOverflowException
. Это напоминает мне, что, когда Том Круз играет Джон Андертон, он сказал, что: "Но это не упало, ты его поймал. Тот факт, что ты предотвратил это, не меняет того факта, что это произойдет".
Некоторые хорошие способы избежать нелогичных проблем?
Код компилируемый и проверяемый, обратите внимание, что перед компиляцией необходимо определить один из OPTION_1
до OPTION_4
shoule.
-
Простой тест
var objects=new object[] { }; Debug.Print("{0}", objects.IsInfinity()); var infObjects=objects.AsInterminable(); Debug.Print("{0}", infObjects.IsInfinity());
-
<сильные > Классы
using System.Collections.Generic; using System.Collections; using System; public static partial class Interminable /* extensions */ { public static Interminable<T> AsInterminable<T>(this IEnumerable<T> x) { return Infinity.OfType<T>(); } public static Infinity AsInterminable(this IEnumerable x) { return Infinity.OfType<object>(); } public static bool IsInfinity(this IEnumerable x) { var it= x as Infinity??((Func<object>)(() => { var info=x.GetType().GetField("source", bindingAttr); return null!=info?info.GetValue(x):x; }))(); return it is Infinity; } const BindingFlags bindingAttr= BindingFlags.Instance|BindingFlags.NonPublic; } public abstract partial class Interminable<T>: Infinity, IEnumerable<T> { IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } #if OPTION_1 public IEnumerator<T> GetEnumerator() { for(var message="Attempted to enumerate an infinite enumerable"; ; ) throw new InvalidOperationException(message); } #endif #if OPTION_2 public IEnumerator<T> GetEnumerator() { foreach(var x in this) yield return x; } #endif #if OPTION_3 public IEnumerator<T> GetEnumerator() { return this.GetEnumerator(); } #endif #if OPTION_4 public IEnumerator<T> GetEnumerator() { throw new StackOverflowException("... "); } #endif public Infinity LongCount<U>( Func<U, bool> predicate=default(Func<U, bool>)) { return this; } public Infinity Count<U>( Func<U, bool> predicate=default(Func<U, bool>)) { return this; } public Infinity LongCount( Func<T, bool> predicate=default(Func<T, bool>)) { return this; } public Infinity Count( Func<T, bool> predicate=default(Func<T, bool>)) { return this; } } public abstract partial class Infinity: IFormatProvider, ICustomFormatter { partial class Instance<T>: Interminable<T> { public static readonly Interminable<T> instance=new Instance<T>(); } object IFormatProvider.GetFormat(Type formatType) { return typeof(ICustomFormatter)!=formatType?null:this; } String ICustomFormatter.Format( String format, object arg, IFormatProvider formatProvider) { return "Infinity"; } public override String ToString() { return String.Format(this, "{0}", this); } public static Interminable<T> OfType<T>() { return Instance<T>.instance; } }