我有几个值要放入字典中:
// Pretend these values are retrieved from a database or something
string firstName = "John";
string lastName = "Smith";
List<string> listHobbies = new List<string> () {"hockey","soccer"};
var dict = new Dictionary<string, dynamic>()
{
{"firstName", firstName},
{"lastName", lastName},
{"hobbies", listHobbies}
};
Run Code Online (Sandbox Code Playgroud)
但是,在某些情况下,List<string>变量可能是空列表。如果是这种情况,我不想将{"hobbies", listHobbies}键添加到生成的字典中。
有没有办法在字典的集合初始值设定项中实现这个检查?还是我坚持使用 if 语句来检查列表的大小并在声明后立即删除密钥?
编辑:本质上,我想知道 C# 是否允许这样的事情:
var dict = new Dictionary<string, dynamic>()
{
{"firstName", firstName},
{"lastName", lastName},
{"hobbies", listHobbies} unless (listHobbies.Count == 0) // don't add the "hobbies" key if the list is empty.
};
Run Code Online (Sandbox Code Playgroud)
我目前可以通过做这样的事情来实现这一点:
var dict = new Dictionary<string, dynamic>()
{
{"firstName", firstName},
{"lastName", lastName},
{"hobbies", listHobbies}
};
}.Concat(listHobbies != 0 ? new Dictionary<string, dynamic>() { { "hobbies", listHobbies } } : new Dictionary<string, dynamic>()).ToDictionary(k => k.Key, v => v.Value);
Run Code Online (Sandbox Code Playgroud)
但这是非常丑陋的。
编辑 2: 我找到了一个可以接受的解决方案,如果其他人可以提供更好看的替代方案,请随时提出建议:
var dict = new Dictionary<string, dynamic>()
{
{"firstName", firstName},
{"lastName", lastName},
{"hobbies", !listHobbies.Any() ? listHobbies : null}
}
.Where(entry => entry.Value != null)
.ToDictionary(k => k.Key, v => v.Value);
Run Code Online (Sandbox Code Playgroud)
Dai*_*Dai 10
C# 的集合初始化器只是任何名为 的方法Add(包括扩展方法)的语法糖。无论每个项目之间使用什么 C# 语法,{}都将转换为Add方法参数。
所以这两个语句几乎是相同的(如果在初始化程序完成之前抛出异常,则集合对象生命周期略有不同,但这不值得担心):
// Manually:
Dictionary<String,Foo> dict = new Dictionary<String,Foo>();
dict.Add( "foo1", new Foo(1) );
dict.Add( "foo2", new Foo(2) );
dict.Add( "foo3", new Foo(3) );
dict.Add( "foo4", new Foo(4) );
// Collection-initializer:
Dictionary<String,Foo> dict = new Dictionary<String,Foo>()
{
{ "foo1", new Foo(1) },
{ "foo2", new Foo(2) },
{ "foo3", new Foo(3) },
{ "foo4", new Foo(4) }
};
Run Code Online (Sandbox Code Playgroud)
(这也意味着,如果您认为对象初始化器在某种程度上比重复调用更有效.Add(),或者它们甚至会导致constexpr集合的 C++ 风格编译时预初始化......那么不幸的是您错了:集合初始化器总是至少 O(n)有运行时间 - 如果您需要更有效的初始化,请考虑使用数组支持的数据结构,以便您可以使用预初始化数组)。
Dictionary<String,dynamic>因此,如果您想要条件初始值设定项,请首先使用额外参数为您的集合类型(在本例中)定义扩展方法Boolean condition:
public static class MyDictionaryExtensions
{
public static void Add( this Dictionary<String,dynamic> dict, String key, dynamic value, Boolean condition )
{
if( condition )
{
dict.Add( key, value );
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它:
// Pretend these values are retrieved from a database or something
string firstName = "John";
string lastName = "Smith";
List<string> listHobbies = new List<string> () {"hockey","soccer"};
var dict = new Dictionary<string, dynamic>()
{
{ "firstName", firstName },
{ "lastName" , lastName },
{ "hobbies" , listHobbies, listHobbies.Count > 0 }
};
Run Code Online (Sandbox Code Playgroud)
更好的是:您可以使其通用(并且您可能无论如何都不应该使用dynamic):
public static class MyDictionaryExtensions
{
public static void Add<TKey,TValue>( this Dictionary<TKey,TValue> dict, TKey key, TValue value, Boolean condition )
where TKey : notnull
{
if( condition )
{
dict.Add( key, value );
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是它在 LinqPad 中运行的屏幕截图证明:
但为什么要停在那里呢?您不仅限于参数:例如,Boolean condition您可以使用一些粗糙的逻辑来检查 的状态,或者使用 a来确定每个项目在运行时的条件。this dictFunc<Boolean>
但有一个小警告:您的Add扩展方法的参数不能与原始方法完全Add匹配,否则您的扩展方法将不会被选择,因为扩展方法总是具有较低的优先级。您也不能通过使用显式参数名称(集合初始化程序没有命名参数)来强制选择扩展方法,但您可以使用自定义类型将虚拟参数用作第三个参数struct(因此它实际上为零成本)。
例如,这是我用来用Exception.Data失败请求中的信息简洁地填充 的字典的扩展HttpClient,responseBody如果值为 ,则该扩展会跳过null:
internal readonly struct OnlyIfBodyIsNotNull
{
}
internal static class DictionaryExtensions
{
public static void Add( this IDictionary exDataDict, String key, String? body, OnlyIfBodyIsNotNull _ )
{
if( body != null )
{
exDataDict.Add( key, body );
}
}
}
Run Code Online (Sandbox Code Playgroud)
像这样使用:
public static InvalidOperationException CreateException( String message, HttpResponseHeaders responseHeaders, HttpContentHeaders contentHeaders, String? responseBody = null )
{
return new InvalidOperationException( message )
{
Data =
{
{ "Response.Headers" , responseHeaders.ToString() },
{ "Response.ContentHeaders", contentHeaders .ToString() },
{ "Response.Body" , responseBody , default(OnlyIfBodyIsNotNull) }
}
};
}
Run Code Online (Sandbox Code Playgroud)
这有什么问题吗?
var dict = new Dictionary<string, dynamic>()
{
{"firstName", firstName},
{"lastName", lastName}
};
if (listHobbies.Any())
dict.Add("hobbies", listHobbies);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2119 次 |
| 最近记录: |