问题描述
Crystal 中将键插入到 中的规范方式是什么,但如果映射之前确实存在则抛出错误。原则上,代码如下:
public class Program
{
static void Main(string[] args)
{
var config = LoadConfiguration();
var provider = ConfigureServices(config);
ConfigureConsumers(provider);
Console.ReadLine();
}
public static IConfiguration LoadConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json",optional: true,reloadOnChange: true);
return builder.Build();
}
private static ServiceProvider ConfigureServices(IConfiguration configuration)
{
var services = new ServiceCollection()
.AddTransient<IEmailSender,EmailSender>()
.Configure<AuthMessageSenderOptions>(options => configuration.GetSection("SendGridEmailSettings").Bind(options))
.AddEasyNetQ(configuration["QueueConnectionData"]);
return services.BuildServiceProvider();
}
private static void ConfigureConsumers(ServiceProvider provider)
{
var autoSubscriber = new AutoSubscriber(provider.GetrequiredService<IBus>(),"SomePrefix")
{
AutoSubscriberMessagedispatcher = provider.GetrequiredService<IAutoSubscriberMessagedispatcher>()
};
autoSubscriber.Subscribe(new[] { Assembly.GetExecutingAssembly() });
autoSubscriber.SubscribeAsync(new[] { Assembly.GetExecutingAssembly() });
}
}
我想知道是否有可能不散列两次?我想出了这个想法,但恕我直言很难阅读:
map = Hash(String,Int32).new
if map.has_key?("foo")
raise "Mapping already exists"
else
map["foo"] = 42
end
(如果映射存在,Hash 返回旧值。否则,调用块的结果,即 map = Hash(String,Int32).new
if map.put("foo",42) {}
raise "Mapping already exists"
end
并计算为 nil
。)
有推荐的模式吗?
解决方法
性能方面,您已经找到了最佳解决方案。我可能会使用块调用被内联的事实来稍微重写它:
def update(hash,key,value)
hash.put(key,value) { return }
raise "Duplicate entry"
end
但是这里有一个重要的陷阱:哈希值仍然在错误条件下更新:
hash = {"foo" => "bar"}
update(hash,"baz","quux")
pp hash # => {"foo" => "bar","baz" => "quux"}
update(hash,"foo","hello") rescue puts "Failed updating foo" # => Failed updating foo
pp hash # => {"foo" => "hello","baz" => "quux"}
在不侵入内部 API 的情况下,我认为没有办法避免这种情况。实际上,哈希查找并不是很昂贵,毕竟它是为通过键查找值而优化的数据结构。尤其是因为您似乎对提高 API 没问题,这是一项成本更高的操作。所以就我个人而言,我会选择类似于你的第一个例子的东西。