【问题标题】:Cast vs Serialize/Deserialize C#强制转换与序列化/反序列化 C#
【发布时间】:2016-11-29 21:17:35
【问题描述】:

场景

我在基类中有一个virtual 方法,它以object 作为参数。

我在派生类(更具体地说,视图模型)中重写了它,以便从那里处理不同的对象:

public override void SomeMethod(object parameter)
{
    // ...

    base.SomeMethod(parameter);
}

编辑: 澄清一下 - 我无法更改基类中的 SomeMethod 签名 - 不幸的是,我坚持使用 object 作为类型 :(

假设每个派生类都期望下一个派生类具有不同的类型,但我知道每个类需要使用什么类型才能传递和使用它。

特别会问Dictionary<string, string>;但我很想看看这是否适用于其他类型。


想象一下……

所以,假设我有一个Dictionary<string, string> 我想传递给SomeMethod()

这是字典:

// create the dictionary
var myItem = new Dictionary<string, string>
{
    ["Key1"] = "Value1",
    ["Key2"] = "Value2"
    // ...
};

到目前为止我所拥有的......

可能性...

为了将myItem 传递给SomeMethod(),我可以想到两种可能的方法:

// Pass the myItem directly as an object

SomeMethod(myItem);

// Serialize the myItem to a string, and then pass that as an object
// I'm using JsonConvert in this case

object parameter = JsonConvert.SerializeObject(myItem);
SomeMethod(parameter);

消耗物品

然后,我可以使用 2 种可能的方式来使用我刚刚传递给 SomeMethod() 的项目,具体取决于我上面分别使用的方法:

public override void SomeMethod(object parameter)
{
    // Cast the parameter back to a dictionary
    Dictionary<string, string> unboxedItem = parameter as Dictionary<string, string>;

    // consume away...
}

public override void SomeMethod(object parameter)
{
    // Deserialize the parameter from a string
    Dictionary<string, string> deserializedItem =
                    JsonConvert
                    .DeserializeObject<Dictionary<string, string>>(parameter as string);

    // consume away...
}

帮助?

这两种方法中哪一种资源消耗较少?

我听说装箱和拆箱最终会很慢(在大规模情况下)。

是的,我知道我实际上是在第二种方法中对序列化的string 进行装箱 - 就资源而言,我对哪种类型进行装箱/拆箱是否重要?

向/从对象投射会影响性能吗?或者,反序列化会真正影响性能吗?

更新:所以,我似乎有点傻,对装箱/拆箱的东西有误解 - 所以我更新了问题以反映这一点

非常感谢您的 cmets、建议和帮助 :)

【问题讨论】:

  • 这与拆箱无关。演员很便宜;解析非常昂贵
  • 过早的优化是万恶之源。如果你想在这个层面上进行优化,你首先需要了解拳击到底是什么以及为什么它慢。
  • 拳击??否。如果参数类型是动态的,请使用 dynamic 关键字。
  • 其实你应该改用泛型,完全停止使用object
  • 您实际上并没有在该示例中进行拆箱,而只是进行演员表。拆箱是将引用类型传递给值类型。在您的情况下,两者都是引用类型。那么让我看看我是否理解,您希望有一个通用接口将消息传递给链的不同成员?

标签: c# serialization casting deserialization


【解决方案1】:

首先,拳击不是这里发生的事情。装箱是指准备值类型作为引用类型放入堆中的操作。如果您的字典是值类型,则确实需要将其装箱和拆箱。

唉,字典是一种引用类型。这意味着不会有拳击。引用将按原样传递给您的方法。您的方法要做的是将 downcast 转换为字典。虽然这需要评估对象的 RTTI(运行时类型信息),但通常不会注意到性能影响(极端情况除外)。

但是,您的序列化/反序列化解决方案要贵得多。您必须在堆上为字符串分配空间,您必须序列化、反序列化,并且字符串最终需要被垃圾收集。您可以预期这比简单的垂头丧气要昂贵得多。

更新:

为了清楚起见,您仍然可以期望拳击比序列化便宜。因此,即使对于值类型,也没有理由选择序列化。尤其是在整个序列化往返过程中,您很有可能至少进行一次装箱操作。

【讨论】:

  • 感谢您提供此信息 - 非常有用。我认为很明显我误解了装箱/拆箱的工作原理(doh!-咖啡时间...)。我会确保我将来不会不必要地反序列化。再次感谢你:)
猜你喜欢
  • 1970-01-01
  • 2010-10-14
  • 2018-02-20
  • 2011-06-25
  • 1970-01-01
  • 2013-10-12
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多