【问题标题】:How to refactor this?如何重构这个?
【发布时间】:2011-04-13 18:45:21
【问题描述】:

我试图重构这个

class AClass
{
     string Property1 { get; set; }
     string Property2 { get; set; }
     string Property3 { get; set; }

     void AMethod(AClass other)
     {
         if(String.IsNullOrEmpty(this.Property1))
         {
              this.Property1 = other.Property1;
         }

         if(String.IsNullOrEmpty(this.Property2))
         {
              this.Property2 = other.Property2;
         }

         if(String.IsNullOrEmpty(this.Property3))
         {
              this.Property3 = other.Property3;
         }
     }
 }

我唯一能想到的是

    private string GetFirstNotNullOrEmpty(string first, string second)
    {
        if (String.IsNullOrEmpty(first))
        {
            return second;
        }

        return first;
    }

    this.Property1 = GetFirstNotNullOrEmpty(this.Property1, other.Property1);

这并不完全等同,但可以胜任。有没有更好的重构方法?

【问题讨论】:

  • 我添加了一些反射代码来处理 N 个属性。让我们知道这是怎么回事

标签: c# reflection code-snippets


【解决方案1】:

如果您要为该类的 N 个字符串属性执行此操作,则应使用 Reflection 来实现。

更新

都是关于“teh codez”的,对吧?就是这样:

class SomeClass
{
    public string Property0 { get; set; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
    public string Property4 { get; set; }
    public string Property5 { get; set; }
    public string Property6 { get; set; }
    public string Property7 { get; set; }
    public string Property8 { get; set; }
    public string Property9 { get; set; }

    public override string ToString()
    {
        //just to print out all properties and values
        foreach (PropertyInfo prop in typeof(SomeClass).GetProperties())
        {
            Console.WriteLine(prop.Name + "," + prop.PropertyType + " = " + prop.GetValue(this, null));
        }
        return base.ToString();
    }

    public void CopyStringPropertiesIfEmptyFrom(SomeClass SourceInstance)
    {
        foreach (PropertyInfo prop in typeof(SomeClass).GetProperties())
        {
            if (prop.PropertyType == typeof(System.String) && String.IsNullOrEmpty((string)prop.GetValue(this, null)))
            {
                prop.SetValue(this, prop.GetValue(SourceInstance, null), null);
            }
        }
    }

}

【讨论】:

  • 通过使用反射,您甚至可以指定一个属性来判断字符串属性是否“可复制”。怎么会脆弱?
  • o:对不起,我没有考虑清楚。您不必使用魔术字符串来执行此操作。致电this.GetType().GetProperties() 即可。
【解决方案2】:

您可以将 if 折叠成三元运算符,而不是使用方法:

this.Property1 = String.IsNullOrEmpty(this.Property1)? other.Property1 : this.Property1;

【讨论】:

    【解决方案3】:

    在属性本身中实现检查。

    public class AClass
    {
        string Property1 
        { 
            get { return _Property1; }
            set
            {
                if (String.IsNullOrEmpty(_Property1))
                {
                    _Property1 = value
                }
            }
        }
        private string _Property1;
    
    
        void AMethod(AClass other)
        {
            this.Property1 = other.Property1;// Property can only be set once.
        }
    
    }
    

    【讨论】:

    • 那不是重构,代码复制级别是一样的。
    • 不是真的。例如,如果您有两个或三个执行此操作的方法,那么您将实现它们,就好像 Null 检查不存在一样。但是,如果您继续使用原始方法,则必须一遍又一遍地复制空检查。
    • 因为您现在拥有属性上的代码...而不是函数中的代码。无论走到哪里,都保持着“只有在 null 时才改变”的特性。例如,而不是将另一个类传递给 AMethod 方法。您可以只设置要转移的属性(如果该属性为空),这些属性就会转移。 (如果属性为空)我猜它可能没有完成你的任务,因为我不知道你的任务是什么。您的代码示例没有什么意义。
    【解决方案4】:

    当我可以避免它时,我不喜欢使用反射,所以我实际上喜欢你在问题中建议的选项,但与 Tesserex 的回答略有不同:

    private string GetFirstNotNullOrEmpty(string first, string second)
    {
        return String.IsNullOrEmpty(first)) ? second : first;
    }
    

    【讨论】:

      【解决方案5】:

      我认为最好的解决方案是

      private void SetFirstNotNullOrEmpty(string first, string second, Action<T> setter)
      {
          if (String.IsNullOrEmpty(first))
          {
              setter(second);
          }
      }
      

      它会被这样调用:

      this.Property1 = GetFirstNotNullOrEmpty(this.Property1, other.Property1, i => this.Property1 = i);
      

      如果这些不是 C# 属性,那就更好了。使用公共字段,我可以传递引用并将 getter 和 setter 放在一个参数中。

      【讨论】:

        【解决方案6】:

        这里首先需要重构的是不直观的名称,例如 Property1 和 AClass。对类和属性名称使用有意义的名称,以便它们清楚地反映意图。

        可能,OP 希望我们专注于手头的问题,而不是这方面。

        【讨论】:

          猜你喜欢
          • 2022-12-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多