【问题标题】:C# Whay does PropertyInfo.SetValue change source value [duplicate]C#为什么PropertyInfo.SetValue会改变源值[重复]
【发布时间】:2019-09-09 15:07:00
【问题描述】:

我有一个像“缓存”一样使用的静态字典。

在某个地方,我创建了一个新对象并将其某些属性设置为具有字典中的值。

后来,由于某些原因,我使用 PropertyInfo.SetValue 对对象的一些字符串属性进行编码。

问题是 - 字典值也发生了变化。

我尝试在编码之前“复制”字符串,但似乎问题在于 setValue 而不是字符串更改。

Person p = new Person();
//Cache.Countries is a static dictionary of countries
//each Country contains a few properties, not just description
p.Country = Cache.Countries[1];
encodeObj(p.Country);

encodeObj 函数在所有对象属性上运行 foreach,它对给定对象上的所有字符串进行编码。

private void encodeObj(object obj)
{
    foreach(var pi in obj.GetType().GetProperties())
    {
        object propValue = pi.GetValue(obj,null);
        if(pi.PropertyType == typeof(string) && !string,IsNullOrEmpty((string)propValue))
        {
            //the Copy is what I tried but didn't work
            string temp = string.Copy((string)propValue);
            string encoded = WebUtility.HtmlEncode(temp);
            //here is the problematic line
            //if I watch now Cache.Countries[1].<the current property info>
            //it is ok
            pi.SetValue(obj,encoded)
            //here if I watch again Cache.Countries[1].<the current property info>
            //it was changed to the encoded value!  
        }
    }
}       

如何在不更改源字典的情况下设置值?

【问题讨论】:

  • 您应该在将Cache.Countries[1] 分配到任何地方之前克隆它,否则您只是共享同一个对象。在一个地方改变它会在任何地方改变它。
  • 您为什么希望它的行为有所不同?您的缓存与您在 encodeObj 中使用的 obj 具有相同的引用。更改 obj 的任何属性都会更改缓存中对象的属性,因为您正在查看单个实例
  • 考虑仔细阅读 C# 中的 reference 类型和 value 类型。

标签: c#


【解决方案1】:

您的encodeObj(object obj) 方法是直接在obj 上设置值。这意味着传入的对象将被修改。这是传递非结构或其他值类型(例如大多数自定义类)的对象时的默认行为。

为了防止这种情况,您需要在传递给方法之前克隆您的对象,或者修改您的方法以克隆传入的对象并将克隆返回给调用者使用。

进一步阅读
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-reference-type-parameters
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-value-type-parameters

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-06
    • 2019-06-20
    • 2020-07-21
    • 2012-11-23
    • 2010-12-18
    • 2018-07-28
    • 2020-01-11
    • 2023-03-09
    相关资源
    最近更新 更多