我有一个静态类,我在其中使用字典作为查找表来映射.NET类型和SQL类型。这是一个这样的字典的例子:
private static readonly Dictionary<Type, string> SqlServerMap = new Dictionary<Type, string>
{
{typeof (Boolean), "bit"},
{typeof (Byte[]), "varbinary(max)"},
{typeof (Double), "float"},
{typeof (Byte), "tinyint"},
{typeof (Int16), "smallint"},
{typeof (Int32), "int"},
{typeof (Int64), "bigint"},
{typeof (Decimal), "decimal"},
{typeof (Single), "real"},
{typeof (DateTime), "datetime2(7)"},
{typeof (TimeSpan), "time"},
{typeof (String), "nvarchar(MAX)"},
{typeof (Guid), "uniqueidentifier"}
};
然后我在下面有一个公共方法,它传入一个.NET类型,它使用这个字典返回相应的MS SQL Server类型的字符串值。但是,由于这被用作进行数据库查询的查找表,我认为将其设为ConcurrentDictionary
是有意义的。我改成了:
private static readonly IDictionary<Type, string> SqlServerMap = new ConcurrentDictionary<Type, string>
{
{typeof (Boolean), "bit"},
{typeof (Byte[]), "varbinary(max)"},
{typeof (Double), "float"},
{typeof (Byte), "tinyint"},
{typeof (Int16), "smallint"},
{typeof (Int32), "int"},
{typeof (Int64), "bigint"},
{typeof (Decimal), "decimal"},
{typeof (Single), "real"},
{typeof (DateTime), "datetime2(7)"},
{typeof (TimeSpan), "time"},
{typeof (String), "nvarchar(MAX)"},
{typeof (Guid), "uniqueidentifier"}
};
但现在它强调{}
内的所有红色(即ConcurrentDictionary
的所有键值对),错误是:
无法访问私有方法&#39;添加&#39;这里
我不这么认为,因为我将其初始化为private static readonly
,因为我刚刚通过制作public static
版本进行了测试,但我得到了同样的错误。
答案 0 :(得分:14)
只有当集合具有适当签名和可访问性的concatenate.less
方法时,您用于填充集合的集合初始值设定项才有效。 Add
没有公开ConcurrentDictionary
方法,因此您无法使用集合初始值设定项。
您可以通过将Add
作为参数传递给构造函数来提供一些初始数据,也可以使用{{IEnumerable<KeyValuePair<TKey, TValue>>
(或TryAdd
或任何其他方法调用创建AddOrUpdate
后,在循环中创建1}}。
答案 1 :(得分:13)
试试这个
private static readonly IDictionary<Type, string> SqlServerMap =
new ConcurrentDictionary<Type, string>(
new Dictionary<Type, string>()
{
{typeof(Boolean ), "bit" },
{typeof(Byte[] ), "varbinary(max)" },
{typeof(Double ), "float" },
{typeof(Byte ), "tinyint" },
{typeof(Int16 ), "smallint" },
{typeof(Int32 ), "int" },
{typeof(Int64 ), "bigint" },
{typeof(Decimal ), "decimal" },
{typeof(Single ), "real" },
{typeof(DateTime), "datetime2(7)" },
{typeof(TimeSpan), "time" },
{typeof(String ), "nvarchar(MAX)" },
{typeof(Guid ), "uniqueidentifier"}
}
);
更新:如果您使用的是C#6(Roslyn 2.0编译器),则可以使用新的Dictionary Initializers。
private static readonly IDictionary<Type, string> SqlServerMap =
new ConcurrentDictionary<Type, string>
{
[typeof(Boolean )] = "bit" ,
[typeof(Byte[] )] = "varbinary(max)" ,
[typeof(Double )] = "float" ,
[typeof(Byte )] = "tinyint" ,
[typeof(Int16 )] = "smallint" ,
[typeof(Int32 )] = "int" ,
[typeof(Int64 )] = "bigint" ,
[typeof(Decimal )] = "decimal" ,
[typeof(Single )] = "real" ,
[typeof(DateTime)] = "datetime2(7)" ,
[typeof(TimeSpan)] = "time" ,
[typeof(String )] = "nvarchar(MAX)" ,
[typeof(Guid )] = "uniqueidentifier"
};
答案 2 :(得分:3)
作为Servy接受的答案的代码示例,为了在实例化时初始化ConcurrentDictionary
,您可以传递一个类型IEnumerable
(如List
){{1} }}类型到构造函数:
KeyValuePair
答案 3 :(得分:1)
由于您的收藏集不会更改,因此您现在可以使用ImmutableDictionary。 尽管这也与初始化有关,但为此question about initialization提出了一些解决方案:
@LukášLánský提供的一个简单解决方案是
var d = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } }.ToImmutableDictionary();
@IanGriffiths提供的性能更好的版本是
public struct MyDictionaryBuilder<TKey, TValue> : IEnumerable
{
private ImmutableDictionary<TKey, TValue>.Builder _builder;
public MyDictionaryBuilder(int dummy)
{
_builder = ImmutableDictionary.CreateBuilder<TKey, TValue>();
}
public void Add(TKey key, TValue value) => _builder.Add(key, value);
public TValue this[TKey key]
{
set { _builder[key] = value; }
}
public ImmutableDictionary<TKey, TValue> ToImmutable() => _builder.ToImmutable();
public IEnumerator GetEnumerator()
{
// Only implementing IEnumerable because collection initializer
// syntax is unavailable if you don't.
throw new NotImplementedException();
}
}
答案 4 :(得分:0)
正如@Servy在他的回答中所说,集合初始化适用于具有Add
方法的类型。但是,如果存在名称为Add
的扩展方法和适当的签名,它也应该有效。所以你可以为并发字典创建一个。初始化将是线程安全的,因为您使用的是静态字段初始化程序。