sObject 対応付けの考慮事項
sObject を対応付けのキーとして使用する場合には、注意が必要です。sObject のキーの照合は、すべての sObject 項目値の比較に基づいています。sObject を対応付けに追加した後で 1 つ以上の項目値が変更した場合に、この sObject を対応付けから取得しようとすると、null が返されます。これは、項目値が異なるので変更後の sObject が対応付けで見つからないためです。sObject で項目を明示的に変更するか、sObject の挿入後に sObject 変数の ID 項目が自動入力されるなど、sObject 項目がシステムによって暗黙的に変更された場合に、この状況が発生します。次の例に示すように、insert 操作の前に追加された対応付けからこのオブジェクトを取得しようとしても、対応付けエントリは生成されません。
たとえば、sObject の before insert および after insert トリガを使用する場合に、sObject 項目の自動入力がトリガに含まれるという別のシナリオもあります。これらのトリガではクラスで定義された静的対応付けを共有しており、Trigger.New の sObject が before トリガでこの対応付けに追加されると、自動入力される項目で 2 つのセットの sObject が異なるため、after トリガにある Trigger.New の sObject は検出されません。after トリガにある Trigger.New の sObject には、挿入後に入力されるシステム項目 (ID、CreatedDate、CreatedById、LastModifiedDate、LastModifiedById、および SystemModStamp) が含まれます。
1// Create an account and add it to the map
2Account a1 = new Account(Name='A1');
3Map<sObject, Integer> m = new Map<sObject, Integer>{
4a1 => 1};
5
6// Get a1's value from the map.
7// Returns the value of 1.
8System.assertEquals(1, m.get(a1));
9// Id field is null.
10System.assertEquals(null, a1.Id);
11
12// Insert a1.
13// This causes the ID field on a1 to be auto-filled
14insert a1;
15// Id field is now populated.
16System.assertNotEquals(null, a1.Id);
17
18// Get a1's value from the map again.
19// Returns null because Map.get(sObject) doesn't find
20// the entry based on the sObject with an auto-filled ID.
21// This is because when a1 was originally added to the map
22// before the insert operation, the ID of a1 was null.
23System.assertEquals(null, m.get(a1));