栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

我们可以将代表保存在文件中(C#)

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

我们可以将代表保存在文件中(C#)

这是一件非常冒险的事情。

确实可以像其他任何对象一样对委托进行序列化和反序列化,但委托是指向对其进行序列化的程序内部方法的指针。如果在另一个程序中反序列化对象,

SerializationException
则很幸运。

例如,让我们对darin的程序进行一些修改:

class Program{   [Serializable]   public class Foo   {       public Func<string> Del;   }   static void Main(string[] args)   {       Func<string> a = (() => "a");       Func<string> b = (() => "b");       Foo foo = new Foo();       foo.Del = a;       WriteFoo(foo);       Foo bar = ReadFoo();       Console.WriteLine(bar.Del());       Console.ReadKey();   }   public static void WriteFoo(Foo foo)   {       BinaryFormatter formatter = new BinaryFormatter();       using (var stream = new FileStream("test.bin", FileMode.Create, FileAccess.Write, FileShare.None))       {formatter.Serialize(stream, foo);       }   }   public static Foo ReadFoo()   {       Foo foo;       BinaryFormatter formatter = new BinaryFormatter();       using (var stream = new FileStream("test.bin", FileMode.Open, FileAccess.Read, FileShare.Read))       {foo = (Foo)formatter.Deserialize(stream);       }       return foo;   }}

运行它,您将看到它创建了对象,对其进行了序列化,将其反序列化为一个新对象,并在调用

Del
该新对象时返回“
a”。优秀的。好的,现在注释掉对的调用
WriteFoo
,这样程序就可以反序列化对象了。再次运行该程序,您将获得相同的结果。

现在交换a和b的声明并运行程序。kes。现在,反序列化的对象返回“ b”。

发生这种情况是因为实际上要序列化的是编译器分配给lambda表达式的名称。然后,编译器按照查找顺序将名称分配给lambda表达式。

这就是这样做的风险:您没有序列化委托,而是序列化了一个符号。序列化的是符号的
,而不是符号所代表的含义。反序列化对象的行为取决于该符号在反序列化程序中所代表的值。

在某种程度上,所有序列化都是如此。将对象反序列化为与序列化程序不同的实现对象类的程序,然后开始有趣。但是序列化委托将序列化的对象耦合到对其进行序列化的程序的符号表,而不是对象的类的实现。

如果是我,我会考虑明确这种耦合。我将创建一个静态属性

Foo
为a
Dictionary<string,Func<string>>
,用键和函数填充此键,然后将键存储在每个实例中,而不是函数中。这使反序列化程序负责在字典开始反序列化
Foo
对象之前填充字典。在某种程度上,这与使用
BinaryFormatter
序列化委托的方式完全相同。区别在于,这种方法使反序列化程序对符号分配功能的责任更加明显。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/374596.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号