C# 为什么Json.Net在序列化对象时调用Equals方法?

C# 为什么Json.Net在序列化对象时调用Equals方法?,c#,json,json.net,equals,serialization,C#,Json,Json.net,Equals,Serialization,我在使用Newtonsoft.JsonSerializeObject方法时遇到了一个错误。以前有人问过这个问题,但是Newtonsoft的工作人员没有回答为什么会发生这种情况 基本上,当像这样调用SerializeObject时: string json = Newtonsoft.Json.JsonConvert.SerializeObject(from, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All

我在使用Newtonsoft.Json
SerializeObject
方法时遇到了一个错误。以前有人问过这个问题,但是Newtonsoft的工作人员没有回答为什么会发生这种情况

基本上,当像这样调用
SerializeObject
时:

string json = Newtonsoft.Json.JsonConvert.SerializeObject(from, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
public override bool Equals(object obj)
{
    if (obj is CapacityConfiguration == false)
        return false;

    CapacityConfiguration cc = (CapacityConfiguration)obj;
}
我在类中重写的许多
Equals
方法中都会出现错误:

public override bool Equals(object obj)
{
    if (obj == null)
        return false;

    CapacityConfiguration cc = (CapacityConfiguration)obj; // <-- TypeCastException here; other Properties of the same class are sent in as parameter!
}
但真正的问题是: 为什么Json.Net在类的
Equals
方法中发送其他类型的对象?
更具体地说,Json.Net似乎在类中发送了许多其他属性,而不是相同类型的另一个对象

对我来说,这太奇怪了。如有任何意见,将不胜感激

根据VisualStudio,我正在使用“Version8.0.0.0”

更新1

它很容易测试,因为它是可复制的:

public class JsonTestClass
{
    public string Name { get; set; }
    public List<int> MyIntList { get; set; }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        JsonTestClass jtc = (JsonTestClass)obj;
        return true;
    }
}
public类JsonTestClass
{
公共字符串名称{get;set;}
公共列表MyIntList{get;set;}
公共覆盖布尔等于(对象对象对象)
{
if(obj==null)
返回false;
JsonTestClass jtc=(JsonTestClass)obj;
返回true;
}
}
然后将此代码放在Program.cs或其他任何地方:

JsonTestClass c = new JsonTestClass();
c.Name = "test";
c.MyIntList = new List<int>();
c.MyIntList.Add(1);

string json = Newtonsoft.Json.JsonConvert.SerializeObject(c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
JsonTestClass c=新的JsonTestClass();
c、 Name=“测试”;
c、 MyIntList=新列表();
c、 增加(1);
字符串json=Newtonsoft.json.JsonConvert.SerializeObject(c,新的JsonSerializerSettings(){TypeNameHandling=TypeNameHandling.All});
您将获得TypeCast异常:

为什么JsonConvert.SerializeObject会调用
对象.Equals
方法

因为当您使用
JsonConvert.SerializeObject
时,会调用一个方法来检查属性是否重新引用您自己的对象,从而导致无限循环

 private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
CheckForCircularReference
方法中,部分代码使用
Contains
方法,该方法将调用
对象。如果
对象
未实现
IEquatable
接口,则等于

bool exists = (Serializer._equalityComparer != null)
                ? _serializeStack.Contains(value, Serializer._equalityComparer)
                : _serializeStack.Contains(value);
解释

  • \u serializeStack
    是当前正在序列化的对象的列表
  • List.Contains
    方法检查当前属性是否包含在集合中
  • List.Contains
    使用
    EqualityComparer.Default
    ,如果类型实现了它,则使用
    IEquatable
    ,否则使用
    object.Equals
  • 对象值
    参数是您当前的
    属性
    对象

  • 以下是自引用循环的一个示例:

    public class JsonTestClass
    {
        public string Name { get; set; }
        public List<int> MyIntList { get; set; }
        public JsonTestClass Test{get;set;}
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            JsonTestClass jtc = (JsonTestClass)obj;
            return true;
       }
    }
    
    JsonTestClass c = new JsonTestClass();
    c.Name = "test";
    c.Test = c;
    string json = JsonConvert.SerializeObject
                   (c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
    

    你能提供一个吗?这只是为了检测对象图中可能的循环吗?@LasseVågsætherKarlsen好吧,我还没有准备好,没有。我在我的大项目中转换一些数据时正在运行这个,所以我还没有做一个测试项目。我想也许有人可以解释一些众所周知的事情,但我会尝试做一个测试,看看是否可以在那里复制它。在任何情况下,可能的原因是json.net正在查看您是否正在序列化循环对象(直接引用自身的对象)。你的
    Equals(object)
    方法应该准备好处理任何类型,所以不管json.net如何,这就是解决方法。我用上面的“UPDATE 1”更新了我的问题,很容易重现@拉塞夫·戈斯·瑟卡尔森:这是猜测还是你知道这是事实?因为我最初的想法是有一个严重的错误…?好吧,这是设计好的。对我来说足够好了。
    JsonTestClass c = new JsonTestClass();
    c.Name = "test";
    c.Test = new JsonTestClass();
    
    string json = JsonConvert.SerializeObject
           (c, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });