gpt4 book ai didi

c# - 我们可以将委托(delegate)保存在文件中吗 (C#)

转载 作者:IT王子 更新时间:2023-10-29 04:36:30 27 4
gpt4 key购买 nike

我有一个有委托(delegate)成员的类。我可以为该类的每个实例化对象设置委托(delegate),但还没有找到任何方法来保存该对象

最佳答案

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

虽然您确实可以像任何其他对象一样序列化和反序列化委托(delegate),但委托(delegate)是指向对其进行序列化的程序内部方法的指针。如果您在另一个程序中反序列化该对象,您将得到一个 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 的声明并运行程序。哎呀。现在反序列化的对象返回“b”。

这是因为实际被序列化的是编译器分配给 lambda 表达式的名称。编译器会按照找到它们的顺序为 lambda 表达式分配名称。

这就是这样做的风险所在:您不是在序列化委托(delegate),而是在序列化符号。序列化的是符号的,而不是符号委托(delegate)的内容。反序列化对象的行为取决于该符号的值在反序列化它的程序中委托(delegate)什么。

在某种程度上,所有序列化都是如此。将一个对象反序列化为一个以不同于序列化程序的方式实现对象类的程序,然后乐趣就开始了。但是序列化委托(delegate)将序列化对象耦合到序列化它的程序的符号表,而不是对象类的实现。

如果是我,我会考虑将这种耦合明确化。我会创建 Foo 的静态属性那是一个Dictionary<string, Func<string>> ,用键和函数填充它,并将键存储在每个实例中而不是函数中。这使得反序列化程序负责在开始反序列化之前填充字典 Foo对象。在某种程度上,这与使用 BinaryFormatter 完全相同。序列化委托(delegate)正在做的事情;不同之处在于,这种方法使反序列化程序为符号分配函数的责任更加明显。

关于c# - 我们可以将委托(delegate)保存在文件中吗 (C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1132702/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com