首页新闻找找看学习计划

《CLR VIA C#》说序列化时不要使用自动实现属性?

0
悬赏园豆:50 [已解决问题] 解决于 2015-04-22 13:41

如题,在网上找了份具体的描述:

————————————————————————————————————————

http://www.cnblogs.com/xiashengwang/archive/2012/07/18/2598108.html

四,控制序列化和反序列化

将SerializationAttribute这个attribute应用于一个类型时,所有的实例字段(public,private,protected等)都会被序列化(在标记了[Serialization]特性的类型中,不要使用C#的“自动实现属性”来定义属性。这是因为字段名是由编译器自动生成的,而每次重新编译,生成的名称都不同)

————————————————————————————————————————

但是我自己实现了下,是可以的。

代码:

    [Serializable]
    public class SerializeClass
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public override string ToString()
        {
            return string.Format("ID:{0},Name:{1}", ID, Name);
        }
    }

public static void Test7()
        {
            SerializeClass s = new SerializeClass()
            {
                ID = 1,
                Name = "test1"
            };
            BinaryFormatter format = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            format.Serialize(stream, s);
            stream.Position = 0;
            var obj = format.Deserialize(stream) as SerializeClass;
            if (obj != null)
            {
                Console.WriteLine(obj.ToString());
            }
        }

输出:ID:1,Name:test1

请问,书上说的对吗?如果对,是我理解的有问题吗?

风筝blog的主页 风筝blog | 初学一级 | 园豆:76
提问于:2015-04-22 11:01
< >
分享
最佳答案
0

这位同学看书很认真,居然连页脚的文字都看了,表扬一下。

如果按照“每次重新编译,生成的名称都不同”这个逻辑的话,

你的测试是无效的,因为你这是同一个编译。

你试着将序列化持久化到文件,然后在另外一个编译中反序列化看看。

收获园豆:30
爱编程的大叔 | 高人七级 |园豆:29786 | 2015-04-22 11:37

谢谢各位的回复,我生成了一个文件:

SerializeClass s = new SerializeClass()
{
ID = 1,
Name = "test1"
};
BinaryFormatter format = new BinaryFormatter();
FileStream fs = new FileStream("T1.txt", FileMode.Create);
format.Serialize(fs, s);

然后再次运行控制台程序(删掉dll,重新编译后),反序列化:

BinaryFormatter format = new BinaryFormatter();
FileStream fs = new FileStream("T1.txt", FileMode.Open);
var obj = format.Deserialize(fs) as SerializeClass;
if (obj != null)
{
Console.WriteLine(obj.ToString());
}

结果显示:

ID:1,Name:test1

因为我用的是.net 4.0,然后我用试了3.5、2.0等都是一样的,然后我怀疑是机器的原因,找同事帮忙生成了一个txt,结果和我本机生成的txt比对是完全一样的。

但因为我们都是用vs2013的,所以可能C#编译器是一样的。

 

所以书上说的“每次重新编译,生成的名称都不同”应该不对,或者至少不严谨,可能有些机器C#编译器版本不同,会导致生成的字段不同。

 

不过看到生成的txt文件(部分):<Name>k__BackingField ,把命名空间等也加进去了,所以最好还是用Newtonsoft.Json 第三方dll,这个生成的是是类似于:

{"ID":123,"Name":"test232"}

是没有命名空间的,所以推荐用它(不是打广告)。

 

风筝blog | 园豆:76 (初学一级) | 2015-04-22 13:38

@风筝blog: 这里说的是每次自动生成的私有字段名字是不固定的。不是说属性名称。

Rookier | 园豆:647 (小虾三级) | 2015-04-24 14:31
其他回答(3)
0

你看的版太旧了.

收获园豆:10
吴瑞祥 | 园豆:28675 (高人七级) | 2015-04-22 11:34

CLR via C# (第四版)是旧的?我才买了不到两个月,不能这样坑人吧。

支持(0) 反对(0) 爱编程的大叔 | 园豆:29786 (高人七级) | 2015-04-22 11:38

@爱编程的大叔: 大叔说的对.不过我一直都在用自动属性做序列化.没出过问题..

支持(0) 反对(0) 吴瑞祥 | 园豆:28675 (高人七级) | 2015-04-22 11:49
0

自动实现属性:

只是会生成具有 k__BackingField 后缀的字段

使用非自动实现属性,就不会有这个后缀

 

为了避免这个后缀,建议使用 非自动实现属性

 

 

而且只对 青色的三个字段进行序列化,红色三角三个属性是不会被序列化的

收获园豆:10
Yu | 园豆:12944 (专家六级) | 2015-04-22 11:40
0

我觉得你应该理解错了,你把字段名(field)和属性(property)混淆了,编译器自动生成的是字段名,属性名是一样的。原版书的Automatically Implemented Properties小节是这样写的:The name of the backing field for an Automatically Implemented Properties is determined by the compiler. 楼上的图可以看到生成的<ID>k__BackingField是private field。

liaohua | 园豆:202 (菜鸟二级) | 2015-04-22 22:10
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册