我正在做一个性能关键程序(很少学术),我正在寻求尽可能优化(不像它证明"这是"瓶颈).
我有一个自定义字典结构(.NET的包装Dictionary<,>
),我会不断删除一个阶段的项目(按Key
值).我需要Value
删除的项目.现在我必须这样做:
T t;
if !TryGet(key, out t)
return false;
Remove(key);
Run Code Online (Sandbox Code Playgroud)
这是两次查找.我会喜欢这个:
public bool Remove(S key, out T value)
{
// implementation
}
Run Code Online (Sandbox Code Playgroud)
我知道框架中没有任何内容,但是某处有实现吗?如果是这样的话,我会用那个更改我的支持词典.
编辑:嗯,我知道这两个TryGetValue
和Remove
是O(1).只知道是否有任何集合结构只能在一次查找中产生相同的效果.正如我所说,我正在努力尽可能地优化.只是知道.
在做类似的事情时:
int value;
if (dict.TryGetValue(key, out value))
{
if (condition)
{
//value = 0; this copies by value so it doesn't change the existing value
dict[key] = 0;
}
}
else
{
dict[key] = 0;
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以避免索引查找来替换现有值吗?我已经使用TryGetValue验证密钥存在,因此再次通过索引检索值似乎是浪费.
另外,在我的代码的else {}部分中,通常认为在添加新值或替换旧值时使用索引器是一种好习惯,并添加以明确您是在添加而不是替换?或者我应该每次只使用索引器?我学习使用字典的方式,我总是做一个TryGetValue查找,而在else部分我处理没有键存在的情况.
我想测试一个id是否尚未知道,或者,如果已知,则关联值是否已更改.我目前正在使用与此类似的代码,但对于那些不熟悉该模式的人来说很难理解.您是否可以想到一种方法,使其在LOC中保持简短时更具可读性?
string id;
string actual;
string stored;
if (!someDictionary.TryGetValue (id, out stored) || stored != actual) {
// id not known yet or associated value changed.
}
Run Code Online (Sandbox Code Playgroud) 我有这个字典和元组在SetValue()中设置如下: -
var myDict = new Dictionary<string, Tuple<string, string>>();
private void SetValue()
{
var myTuple1= Tuple.Create("ABC", "123");
var myTuple2= Tuple.Create("DEF", "456");
myDict.Add("One", myTuple1)
myDict.Add("Two", myTuple2)
}
Run Code Online (Sandbox Code Playgroud)
我试图在GetValue()中检索元组,如下所示: -
private void GetValue()
{
var myTuple = new Tuple<string, string>("",""); //Is this correct way to initialize tuple
if (myDict.TryGetValue(sdsId, out myTuple))
{
var x = myTuple.Item1;
var y = myTuple.Item2;
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,这是否是从字典中检索元组时初始化元组的正确方法?有更好的代码吗?
var myTuple = new Tuple<string, string>("","");
Run Code Online (Sandbox Code Playgroud) 这段代码有效,但效率低下,因为它重复查找ignored
字典。如何TryGetValue()
在 LINQ 语句中使用字典方法使其更高效?
IDictionary<int, DateTime> records = ...
IDictionary<int, ISet<DateTime>> ignored = ...
var result = from r in records
where !ignored.ContainsKey(r.Key) ||
!ignored[r.Key].Contains(r.Value)
select r;
Run Code Online (Sandbox Code Playgroud)
问题是我不确定如何在 LINQ 语句中声明一个用于 out 参数的变量。
所以,我有一个 Dictionary<KType,VType> Foo
我有一个主题:
void Thread1() {
...
if (!Foo.TryGetValue(key, out v)) {
Foo.Add(new VType());
}
...
}
Run Code Online (Sandbox Code Playgroud)
唯一一次Foo
被另一个线程访问是由a TryGetValue
.
那么,我需要锁多少钱?我可以这样做:
void Thread1() {
...
if (!Foo.TryGetValue(key, out v)) {
lock (syncobj) {
Foo.Add(new VType());
}
}
...
}
void Thread2() {
...
lock (syncobj) {
Foo.TryGetValue(key, out v))
}
...
}
Run Code Online (Sandbox Code Playgroud)
Thread1是程序计算的90%,并且TryGetValue
被多次调用.所以,最好,我不想每次都拨打电话.
我经常使用该模式
bool TryGetX(out X x)
Run Code Online (Sandbox Code Playgroud)
当我需要从可能失败的服务获取数据时。当客户端和服务在尝试检索数据之前都不知道数据是否可用时,我会使用此方法。我从来没有完全满意以这种方式使用out参数,而且我从其他 SO 问题中看到它被认为是一个糟糕的模式。
然而,我还没有看到一个令人信服的替代 API 可以向客户端提示他们的方法调用实际上可能不会返回数据。
我考虑过的替代方案:
X GetX(),如果服务无法提供请求的数据,则GetX()返回null 。我不喜欢这样做,因为很多人不清楚他们是否需要检查是否返回null 。考虑到我在处理过的遗留代码中遇到的空引用异常的数量,人们经常忽略空检查,并且用户会看到一个丑陋的异常框。至少TryGetX方法让客户端清楚数据可能不会返回。即使他们确实检查 null,是否到处都要求if (x == null)真的比TryGetX(out X x)更好?
Try/Catch,如果无法返回数据,GetX()会抛出异常。同样,客户可能没有意识到GetX()会引发异常,即使他们意识到了,你也可以在代码中散布 Try/Catches。
GetXResult GetX(),其中GetXResult类有两个属性:bool Success和X x。这可能是我的首选选择,但随后我有很多结果类,使我的项目变得混乱。
对于返回数据但可能无法返回请求的数据的方法,最好的方法是什么?
我正在梳理一些字典对象以获得一个值,但它们都返回 null,即使当我检查它们是否包含该键时,具有该键的对象也会返回 true。我还可以使用 foreach 遍历每个值以获取基于该键的值......我很迷失
foreach (var item in treeView.SelectedItems)
{
string reportName = item.Header.ToString();
string reportPath = "";
reportsAvail.TryGetValue(reportName, out reportPath);
reports.TryGetValue(reportName, out reportPath);
additionalReports.TryGetValue(reportName, out reportPath);
bool test;
test = reportsAvail.ContainsKey(reportName);
test = reports.ContainsKey(reportName);
test = additionalReports.ContainsKey(reportName);
foreach (var y in reportsAvail)
{
if (y.Key.ToString() == reportName)
{
textBlock1.Text = y.Value;
reportPath = y.Value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是它曾经起作用......我不确定是什么阻止了它
我对C#还有点新鲜......我发现自己一遍又一遍地重复使用特定的程序.在我为个人懒惰写一个辅助方法之前,是否有更短或更少的错误方式来编写这种陈述?
Dictionary<string, string> data = someBigDictionary;
string createdBy;
data.TryGetValue("CreatedBy", out createdBy);
//do that for 15 other values
...
MyEntity me = new MyEntity{
CreatedBy = createdBy ?? "Unknown",
//set 15 other values
...
}
Run Code Online (Sandbox Code Playgroud)
本质上,通过尝试获取值来设置对象的属性,然后如果它为null则使用默认值.我有很多属性,如果我可以的话会更好
MyEntity me = new MyEntity{
CreatedBy = TryToGetValueOrReturnNull(data, "CreatedBy") ?? "Unknown",
...
}
Run Code Online (Sandbox Code Playgroud)
再次,我完全有能力编写自己的帮助函数.在我这样做之前,我正在寻找现有的本机功能或简写.
我尝试TryGetValue
像往常一样在字典上使用,如下代码:
Response.Context.Skills[MAIN_SKILL].UserDefined.TryGetValue("action", out var actionObj)
Run Code Online (Sandbox Code Playgroud)
我的问题是字典本身可能为 null。我可以简单地使用“?”。在 UserDefined 之前,但随后我收到错误:
"cannot implicitly convert type 'bool?' to 'bool'"
Run Code Online (Sandbox Code Playgroud)
我处理这种情况的最佳方法是什么?UserDefined
在使用 TryGetValue 之前是否必须检查是否为 null?因为如果我必须使用Response.Context.Skills[MAIN_SKILL].UserDefined
两次,我的代码可能看起来有点混乱:
if (watsonResponse.Context.Skills[MAIN_SKILL].UserDefined != null &&
watsonResponse.Context.Skills[MAIN_SKILL].UserDefined.TryGetValue("action", out var actionObj))
{
var actionName = (string)actionObj;
}
Run Code Online (Sandbox Code Playgroud) 我一直在使用TryGetValue在我的词典中添加/替换数据.为了区分添加new和替换旧,我同时使用[]和.Add().这导致像这样的代码,如果我实际上没有对检索到的值做任何事情:
private Dictionary<Foo, Bar> dictionary = new Dictionary<Foo, Bar>();
public void Update(Foo foo)
{
Bar bar;
if (dictionary.TryGetValue(foo, out bar)
{
dictionary [foo] = bar;
}
else
{
dictionary .Add(foo, bar);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我实际上没有对检索到的值做任何事情,是否有理由不用这个代替上面的代码?:
public void Update(Foo foo)
{
dictionary[foo] = bar;
}
Run Code Online (Sandbox Code Playgroud)
先感谢您.
啊!嗯,我是要张贴这是一个问题,因为我不知道为什么我看到的错误...但当然现在这么明显,当我看到它.现在把自己打倒在脑袋里.我会把它放在这里以获得乐趣.看看你是否能抓住它.
今晚为我们的WeakDictionary类实现TryGetValue时,我遇到了一些奇怪的事情.我收到错误,我不知道为什么.
这是代码:
public bool TryGetValue(TKey key, out TItem value)
{
WeakReference<TItem> weakReference;
if(_itemStorage.TryGetValue(key, out weakReference))
if(weakReference.TryGetTarget(out value))
return true;
else
value = default(TItem);
return false;
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误:
必须在控制离开当前方法之前将out参数'value'分配给.
对我来说,看起来所有代码路径都会在返回之前设置'value'.
如果第一个'if'失败,'else'子句设置'value'.
但是,如果第一个'if'通过,那么下一行'weakReference.TryGetTarget'设置'value'的原因与我被警告的完全相同(即'TryGetTarget'本身有一个'out'参数,因此它也必须在返回之前在内部设置其输出参数)?
就像我说的那样,我错过了一些明显的东西.(我需要睡觉!)
我不确定我是否完全理解TryGet
方法。
它什么false
时候完全返回——当内部锁被锁定时,这意味着while
如果我想获得价值就应该使用(知道它在那里)?
或者这while
以某种方式嵌入到这个函数内部并返回false
手段 -字典中没有这样的键?
注意。这是否适用于ConcurrentDictionary
-TryAdd
等的所有其他方法?