如何重用StringBuilder obj?

发布于 2024-08-16 08:03:10 字数 8620 浏览 6 评论 0原文

据我所知,如果我声明了一本字典,我可以调用 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 对象,我仍然无法检测有多少对象对我来说足够了。实际上 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

As I know if i declared a dictionary, i could call myDict.Clear() for reusing purpose.

Now if I declared a sb as a StingBuilder obj.

StringBuilder sb = new StringBuilder();

How to reuse sb? thank you.

Acturally i need print all the possible conditions for mainDict.

one of sb expression like this(inclued in the code below)

sb.AppendFormat("{0}/{1}/{2}/{3}, {4}", pair1.Key, pair2.Key, pair3.Key, pair4.Key, pair4.Value);
Console.WriteLine(sb.ToString());

If i declared a lot of StringBuilder objs, i still can't detect how many objs is enough for me. acturally the mainDict is very complex. The code above is a practice only. thanks.


Code updated at Jan 04.

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");
                                                    }
                                            }
                                    }
                            }
                    }
            }         
    }

}

Output like this

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

真心难拥有 2024-08-23 08:03:10

您可以设置长度< /a> 到 0。在 .NET 4.0 中,有一个 Clear() 方法也是如此。正如 Clear 的文档所述:

Clear 是一种方便的方法,
相当于设置Length
当前实例的属性为0
(零)。

所以这没什么大不了的:)

我个人会避免这样做,除非你真的需要 - 我通常只是创建一个新的StringBuilder。在我看来,这更容易理解 - 它更清楚地表明您实际上不再需要前一个对象中的任何东西。

您有什么特殊原因想要重用该对象吗?如果是出于性能原因,您是否测量过性能并发现这是瓶颈?我想如果您有一个容量非常大的实例,并且您想避免再次分配它,那么这可能很重要......但这对我来说感觉有点边缘情况。

(顺便说一句,所有这些也适用于字典。我不记得上次清理字典是什么时候了。)

You can set the Length to 0. In .NET 4.0 there's a Clear() method too. As the docs for Clear state:

Clear is a convenience method that is
equivalent to setting the Length
property of the current instance to 0
(zero).

So it's not a big deal :)

I would personally avoid doing this unless you really need to though - I'd normally just create a new StringBuilder. In my view that's simpler to understand - it makes it clearer that you really don't need anything from the previous object any more.

Do you have any particular reason to want to reuse the object? If it's for performance reasons, have you measured the performance and found this is a bottleneck? I suppose it could be significant if you have an instance with a very large capacity, and you want to avoid allocating it again... but that feels like a bit of an edge case to me.

(All of this applies for dictionaries as well, btw. I can't remember the last time I cleared a dictionary.)

淡写薰衣草的香 2024-08-23 08:03:10

我同意 Jon Skeet 的技术解释,但我觉得作为一名性能架构师,有必要描述为什么这是一个相关问题以及在什么情况下开发人员应该考虑采用这种策略。

许多网站或其他类型的应用程序不必关心高性能。这些开发本质上是微不足道的,因为用户并不强调 .NET 运行时。但是,如果您知道自己正在开发高吞吐量应用程序或设计使您的应用程序能够适应未来的可能结果,那么其他可选的内容很快就会成为需求。

即,并非每个人都在开发 Netflix,但当您知道自己是时,您应该在设计(和测试)时考虑到这一点。

那么,在测量并验证它是否会导致问题之前,为什么要费心这样做呢?

我以帮助开发团队克服这些障碍为生。答案是:几乎没有人进行任何测量。

我可以验证 StringBuilder 是否像字符串分配一样显示在配置文件跟踪中。在高性能场景中,这绝对是一个合理的担忧。 如果您要依赖测量,那么您最好进行实际测量。

如果您正在开发高吞吐量应用程序,请不要陷入连续谬误,认为低吞吐量应用程序和高吞吐量应用程序设计要求是等效的。他们不是。

下面是我使用的一种模式,以便通过使用字符串构建器的方法在 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;
        }

I agree with Jon Skeet's technical explanation, but I felt it worthwhile, as a performance architect, to describe why this a relevant question and under which circumstances developers should consider employing such a tactic.

Many websites, or other types of applications, do not have to concern themselves with high performance. These are trivial in nature to develop because users are not stressing the .NET Runtime. However, if you know you are developing a high-throughput application or designing to future-proof your application for that likely outcome, things that are otherwise optional quickly become requirements.

i.e. Not everyone is developing a Netflix, but when you know you are, you should design (and test) with this in mind.

So, why bother doing this until you've measured and verified it's causing issues?

I do performance profiling for a living helping development teams overcome such obstacles. The answer is: Almost nobody is doing any measuring.

I can verify that StringBuilders show up in profile traces just as well as string allocations. In high performance scenarios this is definitely a valid concern. If you're going to rely on measuring, then you better actually measure.

If you are developing high throughput applications, do not get caught in a continuum fallacy that low-through application and high-through application design requirements are equivalent. They're not.

Here's a pattern I utilize in order to multi-thread string builders inside of a Singleton DI lifetime object with a method using the string builder.

[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;
        }
好菇凉咱不稀罕他 2024-08-23 08:03:10

我认为您应该创建一个新的 StringBuilder 对象,而不是重用现有的 StringBuilder 对象。

I think rather then reusing an exting StringBuilder object, you should create a new StringBuilder object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文