繁体   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