闭包会破坏序列化吗

Do closures break serialization

提问人:chiccodoro 提问时间:11/12/2014 最后编辑:Communitychiccodoro 更新时间:11/12/2014 访问量:743

问:

今天,当 IIS 尝试将会话存储在 ASP.NET State Service 中时,我遇到了一个引用某个匿名内部类,指出它是不可序列化的:SerializationException+<>c__DisplayClass10

程序集“Xyz,Version=1.2.5429.24450,Culture=neutral,PublicKeyToken=null”中的类型“Xyz.GeneralUnderstandingTests+ASerializableType+<>c__DisplayClass10”未标记为可序列化。

我在代码中查找了 lambda,并找到了不少,但其中大多数都不是新的,并且在序列化方面从未出现过任何问题。但后来我注意到我内置了一个新的 lambda 表达式,它“碰巧”构建了一个闭包。

在搜索 Stackoverflow 时,我发现了一些 Q&A 显示闭包不能用其他语言(例如 PHP *)序列化,但我没有设法找到 C# 的此类语句。但是,我已经能够构建一个非常简单的示例,该示例似乎可以确认闭包不可序列化,而“正常”函数是可序列化的closure serialization

[TestFixture]
public class GeneralUnderstandingTests
{
    [Serializable]
    private class ASerializableType
    {
        private readonly Func<int> thisIsAClosure;
        private readonly Func<int> thisIsNotAClosure;

        public ASerializableType()
        {
            const int SomeConst = 12345;
            thisIsNotAClosure = () => SomeConst; // succeeds to serialize

            var someVariable = 12345;
            thisIsAClosure = () => someVariable; // fails to serialize
        }
    }

    [Test]
    public void ASerializableType_CanBeSerialized()
    {
        var sessionStateItemCollection = new 
            System.Web.SessionState.SessionStateItemCollection();
        sessionStateItemCollection["sut"] = new ASerializableType();
        sessionStateItemCollection.Serialize(new BinaryWriter(new MemoryStream()));
    }
}

此测试失败,但一旦注释掉该行,该行就会变为绿色。然而,该行不会引起任何问题,因为它不是一个变量,而是一个常量,也就是说,它不会构建闭包,而是由编译器内联的。thisIsAClosure = ...thisIsNotAClosure = ...SomeConst

你能确认我的结论是正确的吗?

=> 有没有办法规避这个问题?

=> 这可能取决于所用编译器的内部结构吗?因为是编译器将 lambda/closure 表达式转换为匿名内部类。

*) 友情链接:

C# 序列化 Lambda 闭包

评论

2赞 Matias Cicero 11/12/2014
Serialize Composed Func 的可能副本?
1赞 chiccodoro 11/12/2014
@Mati - 宾果游戏!我会帮忙投票的。但是把问题留在这里,因为其他人可能很难像我一样找到另一个问题。因此,您的评论几乎就像是对问题的回答。
0赞 Matias Cicero 11/12/2014
没问题:P。您可能还想查看:在 C# 中序列化和反序列化表达式树,了解序列化解决方法

答: 暂无答案