据我所知,如果我声明了一本字典,我可以调用 myDict.Clear() 进行重用。
现在,如果我将 sb 声明为 StingBuilder 对象。
StringBuilder sb = new StringBuilder();
如何重用某人?谢谢你。
实际上我需要打印 mainDict 的所有可能条件。
像这样的 sb 表达式之一(包含在下面的代码中)
sb.AppendFormat("{0}/{1}/{2}/{3}, {4}", pair1.Key, pair2.Key, pair3.Key, pair4.Key, pair4.Value);
Console.WriteLine(sb.ToString());
如果我声明了很多 StringBuilder objs,我仍然无法检测到有多少 objs 对我来说足够了。实际上 mainDict 非常复杂。上面的代码只是一个练习。谢谢。
代码于 1 月 4 日更新。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
class test
{
private static Dictionary<string, object> mainDict = new Dictionary<string, object>();
public static void Main()
{
Dictionary<string, object> aSubDict = new Dictionary<string,object>();
Dictionary<string, object> aSub1Dict = new Dictionary<string, object>();
Dictionary<string, object> aSub2Dict = new Dictionary<string, object>();
Dictionary<string, object> aSub3Dict = new Dictionary<string, object>();
Dictionary<string, object> aSub4Dict = new Dictionary<string, object>();
mainDict.Add("ADKey", aSubDict);
mainDict.Add("ASKey", "AValue");
aSubDict.Add("BDKey", aSub1Dict);
aSubDict.Add("BSKey", "BValue");
aSub1Dict.Add("CDKey", aSub2Dict);
aSub1Dict.Add("CSKey", "CValue");
aSub2Dict.Add("DDKey",aSub3Dict);
aSub2Dict.Add("DSKey", "DValue");
aSub3Dict.Add("EDKey", aSub4Dict);
aSub3Dict.Add("ESKey", "EValue");
aSub4Dict.Add("FKey", "FValue");
StringBuilder sb;
foreach (KeyValuePair<string, object> pair1 in mainDict)
// watch out for NullReferenceException
if (!ReferenceEquals(null, mainDict[pair1.Key]) && (mainDict[pair1.Key] is string))
{
Console.WriteLine("Key = {0}, Value = {1}", pair1.Key, pair1.Value);
sb = new StringBuilder();
sb.AppendFormat("{0}, {1}", pair1.Key, pair1.Value);
Console.WriteLine(sb.ToString());
}
// IDictionary is not the one from the Generics namespace, it is the one from the System.Collections namespace
else if (!ReferenceEquals(null, mainDict[pair1.Key]) && (mainDict[pair1.Key] is Dictionary<string, object>))
{
foreach (KeyValuePair<string, object> pair2 in (Dictionary<string, object>)pair1.Value)
if (!ReferenceEquals(null, ((Dictionary<string, object>)pair1.Value)[pair2.Key]) && (((Dictionary<string, object>)pair1.Value)[pair2.Key] is string))
{
Console.WriteLine("SubKey = {0}, Value = {1}", pair2.Key, pair2.Value);
sb = new StringBuilder();
sb.AppendFormat("{0}/{1}, {2}", pair1.Key, pair2.Key, pair2.Value);
Console.WriteLine(sb.ToString());
}
else if (!ReferenceEquals(null, ((Dictionary<string, object>)pair1.Value)[pair2.Key]) && (((Dictionary<string, object>)pair1.Value)[pair2.Key] is Dictionary<string, object>))
{
foreach (KeyValuePair<string, object> pair3 in (Dictionary<string, object>)pair2.Value)
if (!ReferenceEquals(null, ((Dictionary<string, object>)pair2.Value)[pair3.Key]) && (((Dictionary<string, object>)pair2.Value)[pair3.Key] is string))
{
Console.WriteLine("SubKey = {0}, Value = {1}", pair3.Key, pair3.Value);
sb = new StringBuilder();
sb.AppendFormat("{0}/{1}/{2}, {3}", pair1.Key, pair2.Key, pair3.Key, pair3.Value);
Console.WriteLine(sb.ToString());
}
else if (!ReferenceEquals(null, ((Dictionary<string, object>)pair2.Value)[pair3.Key]) && (((Dictionary<string, object>)pair2.Value)[pair3.Key] is Dictionary<string, object>))
{
foreach (KeyValuePair<string, object> pair4 in (Dictionary<string, object>)pair3.Value)
if (!ReferenceEquals(null, ((Dictionary<string, object>)pair3.Value)[pair4.Key]) && (((Dictionary<string, object>)pair3.Value)[pair4.Key] is string))
{
Console.WriteLine("SubKey = {0}, Value = {1}", pair4.Key, pair4.Value);
sb = new StringBuilder();
sb.AppendFormat("{0}/{1}/{2}/{3}, {4}", pair1.Key, pair2.Key, pair3.Key, pair4.Key, pair4.Value);
Console.WriteLine(sb.ToString());
}
else if (!ReferenceEquals(null, ((Dictionary<string, object>)pair3.Value)[pair4.Key]) && (((Dictionary<string, object>)pair3.Value)[pair4.Key] is Dictionary<string, object>))
{
foreach (KeyValuePair<string, object> pair5 in (Dictionary<string, object>)pair4.Value)
if (!ReferenceEquals(null, ((Dictionary<string, object>)pair4.Value)[pair5.Key]) && (((Dictionary<string, object>)pair4.Value)[pair5.Key] is string))
{
Console.WriteLine("SubKey = {0}, Value = {1}", pair5.Key, pair5.Value);
sb = new StringBuilder();
sb.AppendFormat("{0}/{1}/{2}/{3}/{4}, {5}", pair1.Key, pair2.Key, pair3.Key, pair4.Key, pair5.Key, pair5.Value);
Console.WriteLine(sb.ToString());
}
else if (!ReferenceEquals(null, ((Dictionary<string, object>)pair4.Value)[pair5.Key]) && (((Dictionary<string, object>)pair4.Value)[pair5.Key] is Dictionary<string, object>))
{
foreach (KeyValuePair<string, object> pair6 in (Dictionary<string, object>)pair5.Value)
if (!ReferenceEquals(null, ((Dictionary<string, object>)pair5.Value)[pair6.Key]) && (((Dictionary<string, object>)pair5.Value)[pair6.Key] is string))
{
Console.WriteLine("SubKey = {0}, Value = {1}", pair6.Key, pair6.Value);
sb = new StringBuilder();
sb.AppendFormat("{0}/{1}/{2}/{3}/{4}/{5}, {6}", pair1.Key, pair2.Key, pair3.Key, pair4.Key, pair5.Key, pair6.Key, pair6.Value);
Console.WriteLine(sb.ToString());
}
else if (!ReferenceEquals(null, ((Dictionary<string, object>)pair5.Value)[pair6.Key]) && (((Dictionary<string, object>)pair5.Value)[pair6.Key] is Dictionary<string, object>))
{
Console.WriteLine("sub Dict Found");
}
}
}
}
}
}
}
}
这样的输出
SubKey = FKey, Value = FValue
ADKey/BDKey/CDKey/DDKey/EDKey/FKey, FValue
SubKey = ESKey, Value = EValue
ADKey/BDKey/CDKey/DDKey/ESKey, EValue
SubKey = DSKey, Value = DValue
ADKey/BDKey/CDKey/DSKey, DValue
SubKey = CSKey, Value = CValue
ADKey/BDKey/CSKey, CValue
SubKey = BSKey, Value = BValue
ADKey/BSKey, BValue
Key = ASKey, Value = AValue
ASKey, AValue
Length
设置为0。在.NET 4.0中也有一个Clear()
方法。作为 Clear
状态的文档:
Clear 是一种方便的方法,它是 相当于设置Length 当前实例的属性为 0 (零)。
所以这没什么大不了的:)
我个人会避免这样做,除非你真的需要——我通常只是创建一个新的
StringBuilder
。在我看来,这更容易理解——它让你更清楚地知道你真的不再需要前一个对象的anything了。
你有什么特别的理由想要重用这个对象吗?如果是出于性能原因,您是否测量过性能并发现这是一个瓶颈?我想如果你有一个容量非常大的实例,并且你想避免再次分配它,这可能很重要……但这对我来说有点像边缘情况。
(所有这些也适用于字典,顺便说一句。我不记得上次清理字典是什么时候了。)
我认为与其重用现有的 StringBuilder 对象,不如创建一个新的 StringBuilder 对象。
我同意 Jon Skeet 的技术解释,但作为性能架构师,我觉得有必要描述为什么这是一个相关问题,以及在什么情况下开发人员应该考虑采用这种策略。
许多网站或其他类型的应用程序不必关心高性能。这些开发本质上是微不足道的,因为用户不会强调 .NET 运行时。但是,如果您知道您正在开发高吞吐量应用程序或设计以针对可能的结果对您的应用程序进行未来验证,那么原本可选的东西很快就会变成必需品。
即不是每个人都在开发 Netflix,但当你知道自己在开发 Netflix 时,你应该在设计 (和测试) 时考虑到这一点。
那么,在您测量并验证它导致问题之前,为什么还要费心这样做呢?
我以做性能分析为生,帮助开发团队克服这些障碍。答案是:几乎没有人在做任何测量。
我可以验证 StringBuilders 与字符串分配一样出现在配置文件跟踪中。在高性能场景中,这绝对是一个值得关注的问题。 如果你要依靠测量,那么你最好实际测量。
如果您正在开发高吞吐量应用程序,请不要陷入低吞吐量应用程序和高吞吐量应用程序设计要求相同的连续谬误。他们不是。
这是我使用的一种模式,以便使用字符串构建器的方法在 Singleton DI 生命周期对象内多线程字符串构建器。
[ThreadStatic]
static StringBuilder? _builder;
static StringBuilder builder => _builder.InitializeIsNull(() => new StringBuilder(1000));
/// <summary>
/// Uses pass-by-reference semantics of class to initialize and set reference.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="initialized"></param>
/// <param name="initialize"></param>
/// <returns></returns>
public static T InitializeIsNull<T>(this T? initialized, Func<T> initialize) where T : class
{
if (initialized == null)
{
initialized = initialize();
}
return initialized;
}