問題タブ [custom-collection]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
ios - セル サイズが異なる UICollectionView
私の目標は、UICollectionView
以下に示すようなレイアウトで を作成することです。
カスタムを作成せずにこれは可能UICollectionViewLayout
ですか?
c# - 変更を追跡するために、ObservableCollection をラッパー コレクションとして有効にする方法は?
かなり単純な質問だと思いますが、それに対するより良い解決策をまだ見つけることができません。そこで、この件について調査した後、専門家の意見を得るためにここでこの質問をすることを考えました.
基本的に、私はWPFアプリケーションに取り組んでおり、GenericObserableCollection<T>
実装ObservableCollection<T>
を定義しており、ほとんどのコレクションはそれを実装して、プロジェクト全体で標準的なアプローチをとっています。
最初はすべて問題ありませんでしたが、後でEntity Frameworkが登場したときに、EF ではICollection<T>
マッピングのために公開する必要があるため、ドメインの設計を大幅に変更する必要がありました。その時点で、私は最小限の変更を維持して EF に適応することに混乱していました。
後で調査した後、このシナリオを扱っているいくつかの優れた記事に出くわしました.
EF の要件としてChildrenStorage
保持するアプリケーション ドメインの作成にも同じアプローチを適用しました。ICollection<GenericRule>
現在、アイテムが追加および/または削除されたときに、コレクションChildrenStorage
とコレクションの両方を同期させるためのスマートでエレガントなアプローチを探しています。Children
collection は UI を介して変更されるものであるためChildren
、変更を追跡し、Children
同期したいと考えていChildrenStorage
ます。
excel - x64 カスタム クラスでの For Each 列挙のバグ
数か月前に VBA のバグを発見しましたが、適切な回避策を見つけることができませんでした。このバグは、優れた言語機能を制限するようなものなので、本当に厄介です。
For Each
カスタム コレクション クラスを使用する場合、クラスをループで使用できるように列挙子が必要になることはよくあります。これは、次の行を追加することで実行できます。
次のいずれかの方法で、関数/プロパティ シグネチャ行の直後に挿入します。
- クラス モジュールをエクスポートし、テキスト エディタで内容を編集してからインポートし直す
- 関数シグネチャの上にラバーダックアノテーションを使用してから同期する
'@Enumerator
残念ながら、x64 では、上記の機能を使用すると、間違ったメモリが書き込まれ、場合によってはアプリケーションがクラッシュします (後述)。
バグの再現
CustomCollection
クラス:
標準モジュールのコード:
メソッドを実行するMain
と、コードはメソッドのAssert
行で停止し、[ローカル]ウィンドウで、ローカル変数の値がどこからともなく変更されたShowBug
ことを確認できます。ここで、 ptr1
は に等しいです。メソッド内でより多くの変数が使用される(オプションのパラメーターを含む) ほど、値 (メモリ アドレス) が書き込まれるメソッド内のより多くの ptr が取得されます。
ObjPtr(c)
NewEnum
ShowBug
言うまでもなく、メソッド内のローカルptr変数を削除するShowBug
と、アプリケーションのクラッシュが確実に発生します。
コードを 1 行ずつステップ実行すると、このバグは発生しません。
バグの詳細
Collection
このバグは、内に格納されている実際のものとは関係ありませんCustomCollection
。NewEnum 関数が呼び出された直後にメモリが書き込まれます。したがって、基本的に次のいずれかを実行しても効果はありません (テスト済み):
Optional
パラメータの追加- 関数内からすべてのコードを削除します(これを示す以下のコードを参照)
IUnknown
の代わりとして宣言するIEnumVariant
Function
として宣言する代わりにProperty Get
- メソッド シグネチャで
Friend
orのようなキーワードを使用するStatic
- DISPID_NEWENUM をGetのLetまたはSetに対応するものに追加するか、前者を非表示にします (つまり、Let/Set をプライベートにします)。
上記のステップ 2 を試してみましょう。次の場合CustomCollection
:
テストに使用されるコードは次のように変更されます。
実行Main
すると同じバグが発生します。
回避策
バグを回避するために私が見つけた信頼できる方法:
メソッドを呼び出して (基本的には
ShowBug
メソッドから離れて)、戻ってきます。これは、For Each
行が実行される前に発生する必要があります (同じメソッド内のどこにでもある可能性があることを意味する前に、必ずしも正確な行の前にあるとは限りません)。短所:忘れやすい
Set
ステートメントを行います。ループで使用されるバリアントにある可能性があります (他のオブジェクトが使用されていない場合)。上記のポイント 1 のように、これはFor Each
行が実行される前に発生する必要があります。Set c = c
Or を使用してコレクションをそれ自体に設定し、 cパラメーターByVal
をShowBug
メソッドに渡すことによっても (Set として、IUnknown::AddRef を呼び出します)
短所: 忘れやすいEnumHelper
列挙に使用された唯一のクラスである別のクラスを使用します。CustomCollection
次のようになります。および呼び出しコード:
明らかに、予約済みの DISPID は
CustomCollection
クラスから削除されました。長所:カスタムコレクションを直接ではなく
For Each
、関数に強制します。.NewEnum
これにより、バグによるクラッシュが回避されます。短所:常に余分な
EnumHelper
クラスが必要です。.NewEnum
行に を追加するのを忘れがちFor Each
です (実行時エラーが発生するだけです)。
最後のアプローチ (3) が機能するのは、c.NewEnum
が実行されるとメソッドが終了し、クラス内のShowBug
呼び出しの前に返されるためです。基本的には(1)がバグを回避する方法です。Property Get EnumVariant
EnumHelper
この動作の説明は何ですか? このバグをよりエレガントな方法で回避できますか?
編集
ByVal を渡すことCustomCollection
は常にオプションではありません。を検討してくださいClass1
:
そして今、呼び出しルーチン:
明らかに、この例は少し強引ですが、「子」オブジェクトのカスタム コレクションを含む「親」オブジェクトを持ち、「親」が「子」の一部またはすべてを含む何らかの操作を実行することは非常に一般的です。
この場合、行Set
の前にステートメントまたはメソッド呼び出しを行うことを忘れがちです。For Each