C#は素人なので定石がわかりません。
こういう連想配列があったとしましょう。
$datetimes = [
'past' => [
'yesterday' => new DateTime('yesterday'),
'lastweek' => new DateTime('last week'),
],
'future' => [
'tomorrow' => new DateTime('tomorrow'),
'nextyear' => new DateTime('next year'),
]
];
いや、こんな意味のわからない配列なんて作らねえよという抗議は全くもってその通りなのですがそこはスルーします。
実際はAPIに飛んできたリクエストをユーザ単位にまとめるみたいな処理をするところで、何個飛んでくるかわからないという仕様です。
PHPで書くとこんな感じでさくっとできます。
$datetimes = [];
foreach($request as $v){
$datetimes[$v['tense']][$v['key']] = new DateTime($v['value']);
}
一瞬で書けてとってもらくちん。
ということで、この連想配列をC#に移植しようとしたのですが、どうもこのような構造について話をしているところがほとんど見当たりませんでした。
多重連想配列はC#では禁忌なのだろうか。
連想配列はDictionaryを使えばいいみたいですが、これは基本的に値がひとつです。
NameValueCollectionというのが目的に近かったのですが、これは値がstring
固定みたいです。なぜ。
Microsoft.Experimental.Collectionsは名前が既に危ない。
試しにDictionary
の中にDictionary
を突っ込んでみたら普通にいけました。
var datetimes = new Dictionary<string, Dictionary<string, DateTime>>();
var list1 = new Dictionary<string, DateTime>();
list1.Add("yesterday", new DateTime("yesterday"));
list1.Add("lastweek", new DateTime("last week"));
var list2 = new Dictionary<string, DateTime>();
list2.Add("tomorrow", new DateTime("tomorrow"));
list2.Add("nextyear", new DateTime("next year"));
datetimes.Add("past", list1);
datetimes.Add("future", list2);
ただ、この構造だとlist1
などの中間変数が必要になってしまいます。
一気にdatetimes["past"].Add("yesterday", new DateTime("yesterday"));
みたいなことはできないの?
var datetimes = new Dictionary<string, Dictionary<string, DateTime>>();
// The given key "past" was not present in the dictionary
datetimes["past"].Add("yesterday", new DateTime("yesterday"));
// Object reference not set to an instance of an object
datetimes.Add("past", null);
// An item with the same key has already been added
datetimes.Add("past", new Dictionary<string, DateTime>{{"yesterday", new DateTime("yesterday")}} );
datetimes.Add("past", new Dictionary<string, DateTime>{{"lastweek", new DateTime("last week")}} );
// これはOK
datetimes.Add("past", new Dictionary<string, DateTime>{{"yesterday", new DateTime("yesterday")}} );
datetimes["past"].Add("lastweek", new DateTime("last week"));
Add自体はできるみたいですが、親Dictionaryのキーの有無によって動作を変えなければなりません。
キーが存在しない場合のみキーをAddし、その後はその中身だけAddしないといけないようです。
なんというかとても面倒。
もっとなんかマシな方法ってのがあるんだろうけどよくわかりませんでした。
そもそもC#ではどういう作りにするのが定石なんだろうか。