簡體   English   中英

在C#中迭代動態對象的最快方法是什么?

[英]What is the fastest way to iterate a dynamic object in C#?

背景

我正在開發一個需要在服務器上使用JSON服務的應用程序,然后將該JSON重新打包到可以在視圖中使用Razor語法引用的視圖模型中。 出於各種原因,必須對此代碼進行服務器端操作。

我們使用的是C#,.NET 4,MVC3,Razor,JsonFx。

我們目前的代碼工作得很好,但是在接收到的JSON對象中迭代250個項目需要花費一分鍾時間,這是不可接受的(更不用說令人費解了)。 我已經將問題隔離到以下循環中; JSON快速閃電,這不是問題所在。 這是工作但速度極慢的代碼:

        var reader = new JsonReader();
        var json = GetJson(SPListName);

        var admItems = new List<IDictionary<String, object>>();
        dynamic _items = reader.Read(json); //This part is REALLY fast.  No problem here.
        foreach (var itm in _items)
        {
            dynamic obj = new ExpandoObject();
            foreach (dynamic admObj in itm)//Here begins the slow part.
            {
                var item = obj as IDictionary<String, object>;
                var encodedValue = "";
                try
                {
                    if(admObj.Key == "Title")
                    {
                        encodedValue = admObj.Value.ToString();
                    }else
                    {
                        encodedValue = admObj.Value[0].ToString();
                    }
                }
                catch (Exception)
                {
                    encodedValue = admObj.Value.ToString();                   
                }

                item[admObj.Key] = encodedValue.EncodeNonAscii().FixHtmlEntities();
            }
            admItems.Add(obj);
        }
        return admItems;

您可能還會注意到一些自定義擴展方法。 他們在這里(如果重要的話):

public static string EncodeNonAscii(this Object str)
            {
                StringBuilder sb = new StringBuilder();
                foreach (char c in str.ToString())
                {
                    if (c > 127)
                    {
                        // This character is too big for ASCII
                        string encodedValue = "\\u" + ((int) c).ToString("x4");
                        sb.Append(encodedValue);
                    }
                    else
                    {
                        sb.Append(c);
                    }
                }
                return sb.ToString();
            }

            public static string FixHtmlEntities(this Object str)
            {
                var fixedString = str.ToString().Replace("\\u00c2\\u00ae", "&reg;");
                return fixedString;
            }

我到底做錯了什么/如何加快速度呢? 我的大腦現在是漢堡包,所以我希望有人指出一個簡單的疏忽。

更新/分辨率

Rophuine和Joshua Enfield都指出了速度問題的根源:捕獲異常會減慢一切。

很多人建議我使用Json.Net或類似的東西。 雖然我很欣賞這個建議,但它確實不是我問題的根源(即使它可能是這樣出現的); 我過去曾經廣泛使用過Json.Net,幾個月前更喜歡JsonFx 在這種特殊情況下,我更關心構建視圖模型對象,因為我已經使用JsonFx對JSON進行了反序列化。 如果你仍然認為我錯過了你的觀點,請告訴我;)。

我的腦死亡嘗試/捕獲方案的原因是我需要對JSON字符串的每個屬性做不同的事情,具體取決於它的類型(字符串,字符串[],對象[]等)。 我忘了System.Type可以為我處理。 所以這是最終的代碼:

var reader = new JsonReader();
                var json = GetJson(SPListName);

                var admItems = new List<IDictionary<String, object>>();
                dynamic _items = reader.Read(json);
                foreach (var itm in _items)
                {
                    dynamic obj = new ExpandoObject();
                    foreach (dynamic admObj in itm)
                    {
                        var item = obj as IDictionary<String, object>;
                        var encodedValue = "";

                        Type typeName = admObj.Value.GetType();

                        switch (typeName.ToString())
                        {
                            case("System.String[]"):
                                encodedValue = admObj.Value[0].ToString();
                                break;
                            default:
                                encodedValue = admObj.Value.ToString();
                                break;
                        }

                        item[admObj.Key] = encodedValue.EncodeNonAscii().FixHtmlEntities();
                    }
                    admItems.Add(obj);
                }
                return admItems;

希望這有助於某人!

            try
            {
                if(admObj.Key == "Title")
                {
                    encodedValue = admObj.Value.ToString();
                }else
                {
                    encodedValue = admObj.Value[0].ToString();
                }
            }
            catch (Exception)
            {
                encodedValue = admObj.Value.ToString();                   
            }

我面前沒有C#編譯器,也無法訪問您的數據,但這對我來說很可疑。 例外情況非常緩慢 - 你經常遇到陷阱嗎? 如果是的話,嘗試找出造成異常的原因並處理它們而不會導致異常 - 請保留異常以處理您未曾想到的罕見情況。

編輯:最終解決方案在問題編輯中 - 我不會在這里重復。 如果您遇到性能問題並且在循環中的某個地方進行了異常處理,那么這通常是首先嘗試消除的問題。 例外情況非常緩慢 - 遠比你想象的要多得多。 他們最好保留在非常特殊的情況下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM