次の問題に出くわしました:
class Settings
{
// Let's set some default value: { 1 }
public ICollection<int> AllowedIds = new List<int>() { 1 };
}
static void Main(string[] args)
{
var s = new Settings
{
AllowedIds = { 1, 2 }
};
Console.WriteLine(string.Join(", ", s.AllowedIds)); // prints 1, 1, 2
}
これが起こる理由を理解しています: AllowedIds = { 1, 2 }
は割り当てではなく、オブジェクト初期化子内のコレクション初期化子です。つまり、 の暗黙的な呼び出しですAllowedIds.Add(1); AllowedIds.Add(2)
。
それでも、割り当てのように見えるので、私にとっては落とし穴でした( を使用しているため=
)。
API/ライブラリ開発者 (私がクラスを開発しているとしましょう)として、最小の驚きの原則をSettings
守りたいと思っていますが、ライブラリの消費者がその罠に陥るのを防ぐためにできることはありますか?
脚注:
その特定のケースでは、 の
ISet/HashSet<int>
代わりに を使用できますICollection/List
(重複は には意味がないためAllowedIds
)1, 2
。それでも、初期化AllowedIds = { 2 }
すると直観に反する結果が得られ1, 2
ます。C# github repoで関連する議論を見つけました。基本的に、この構文は紛らわしいですが、これは古い機能 (2006 年に導入された) であり、後方互換性を壊すことなく変更することはできません。