抱歉 - 这应该是根据' ref'提交的。参数。我正在关注这个问题并没有真正思考。答案是ModifiedSerialized函数应该使用ref参数来修改' target'直接
ModifySerialized(ref DataClass target){...}
鉴于此runtime.serializable类:
[DataContract]
public class DataClass
{
[DataMember(Order = 0)]
public int Number
{
get;
set;
}
[DataMember(Order = 1)]
public string Name
{
get;
set;
}
override public string ToString()
{
return "DataClass: " + Name + " -- " + Number;
}
}
和一些锻炼课程:
class Test
{
public Test()
{
DataClass testDataClass = new DataClass() { Name = "Foo", Number = 123 };
ModifySerialized(testDataClass);
Console.WriteLine(testDataClass);
}
private void ModifySerialized(DataClass target)
{
MemoryStream stream = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(typeof(DataClass));
serializer.WriteObject(stream, new DataClass() { Name = "serialized", Number = 777 });
stream.Seek(0, SeekOrigin.Begin);
string sDebug = ASCIIEncoding.ASCII.GetString(stream.GetBuffer());
Console.WriteLine(sDebug);
target = (DataClass)serializer.ReadObject(stream);
Console.WriteLine(target);
}
}
我希望在调用ModifySerialized(target)
之后,在Test ctr中输出到控制台是这样的:
DataClass: name = serialized -- number = 777
但是,调用ModifySerialized(target)
后的输出仍会显示
DataClass: name Foo number 123 (or similar)
- > (DataClass)目标未被修改
但是,在对ModifySerialized
的函数调用中,控制台输出是我对“目标”所期望的。 (即序列化,777)。
我错过了什么?函数的参数是参考,不是吗?应该修改引用的值,不是吗?相反,如果在ModifySerialized(target)
内{我只设置Number=1234
,则在按照预期从Test调用后,该值将正确输出到控制台。
谢谢......
答案 0 :(得分:3)
在ModifySerialized
方法中,您将target
参数设置为DataClass
的新实例;但是,由于参数未通过引用传递,testDataClass
方法中的Test
变量仍然引用从未修改过的原始实例。通过引用传递参数将产生您期望的行为。
我错过了什么?函数的参数是参考,不是吗?应该修改引用的值,不是吗?相反,如果在ModifySerialized(target)中,我只设置Number = 1234,那么在按照预期从Test调用后,该值将正确输出到控制台。
我认为你在这里混淆了两个概念:
这里,参数的类型是引用类型,这意味着参数的值是引用;但是引用是按值传递的,因此为参数指定新实例不会更改原始引用。
有关更详细的解释,我建议您阅读Jon Skeet的优秀文章:Parameter passing in C#
答案 1 :(得分:0)
您希望原始变量testDataClass
的值会更改,但它不会像这样工作。它的值的副本实际上传递给方法,并且在执行期间被查询,但它不能反映到原始变量。为此,您应该返回新值作为方法结果:
private DataClass ModifySerialized(DataClass target)
{
MemoryStream stream = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(typeof(DataClass));
serializer.WriteObject(stream, new DataClass() { Name = "serialized", Number = 777 });
stream.Seek(0, SeekOrigin.Begin);
string sDebug = ASCIIEncoding.ASCII.GetString(stream.GetBuffer());
Console.WriteLine(sDebug);
target = (DataClass)serializer.ReadObject(stream);
Console.WriteLine(target);
return target; // here
}
public Test()
{
DataClass testDataClass = new DataClass() { Name = "Foo", Number = 123 };
testDataClass = ModifySerialized(testDataClass);
Console.WriteLine(testDataClass);
}
或使用ref。
private DataClass ModifySerialized(ref DataClass target)
{
MemoryStream stream = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(typeof(DataClass));
serializer.WriteObject(stream, new DataClass() { Name = "serialized", Number = 777 });
stream.Seek(0, SeekOrigin.Begin);
string sDebug = ASCIIEncoding.ASCII.GetString(stream.GetBuffer());
Console.WriteLine(sDebug);
target = (DataClass)serializer.ReadObject(stream);
Console.WriteLine(target);
}
public Test()
{
DataClass testDataClass = new DataClass() { Name = "Foo", Number = 123 };
ModifySerialized(ref testDataClass);
Console.WriteLine(testDataClass);
}
答案 2 :(得分:0)
请记住,serializer.ReadObject
会返回刚从流中读取的新对象。它将替换函数中target
变量记住的对象,但此操作不会更改外部变量记住的内容。
为此,请尝试ModifySerialized(ref DataClass target)
。但仍然要记住它不会“改变对象内容”。它将忘记旧实例并将其替换为新实例。
您可以在调试器中通过“Make Object ID”检查它,看看哪个变量引用对象#1,哪个变量引用#2等