コードが更新されました
フィルタリングされた のバグを修正するため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
定数として宣言されています。
概要
無限の列挙可能なを実装しようとしていますが、非論理的な何かに遭遇し、一時的にアイデアが不足しています。コードを完成させ、セマンティックで論理的で合理的なデザインにするための方向性が必要です。
一部始終
私は数時間前に質問しました:
これは、実装の適切なパターンではない可能性があります。私がやろうとしているのは、論理的かつセマンティックな方法で、無限を表す列挙可能なものを実装することです(私は..と思いました)。この投稿の最後にコードを配置します。
大きな問題は、それは無限の列挙可能なものを提示するためだけのものですが、その列挙には実際の要素がないため、実際には意味がありません。
したがって、列挙にダミー要素を提供する以外に、私が想像できる 4 つのオプションがあり、そのうちの3 つが
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
。これは、トム・クルーズが演じたとき、ジョン・アンダートンが次のように言ったことを思い出させます。
非論理的な問題を回避する良い方法はありますか?
コードはコンパイル可能でテスト可能です。コンパイル前に to の 1 つを定義する必要があることに注意してOPTION_1
くださいOPTION_4
。
簡単なテスト
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; } }