具有只读字段的TryParse模式/非默认构造函数

jas*_*per 2 c#

人们通常如何使用TryParse模式实现解析构造函数,当它们具有只读备份字段时,以及非默认构造函数,通常会进行解析?

下面是我正在谈论的一个人为的例子,以及我已经确定的模式,但看起来很笨拙.实际上,一些类型具有大量属性.当然,我可以创建一个方法来获取n参数,进行解析,并以这种方式连接它们,但在某些情况下使用带有15个参数的方法也是一种痛苦/恶臭.

两个构造函数的想法,加上必须将try解析的结果复制到解析构造函数中的只读字段,这有点令人闻到.

其他人有更好的模式吗?

编辑:提供更多上下文

我正在尝试做的是重构一个大的(ish)代码库,它有很多类型,如下面的例子,其中有解析提供给构造函数的字符串参数.现在,所有代码都使用构造函数解析,并且此解析的逻辑都在构造函数中完成.凌乱而又麻烦.

我想做的第一件事就是将这段代码从构造函数中移到工厂方法(TryParse)中,但是保留了构造函数签名,所以我对代码库没有太多的改动.从长远来看,有时间可以做得更好.

目前,难点在于保持现有代码的结构签名完整,同时允许新代码使用TryParse模式,并保留只读字段.如果我放松了readonly字段,整个过程会更容易,但我宁愿不这样做.

public class Point
{
   private readonly float x, y;
   public float X { get { return x; } }
   public float Y { get { return y; } }

   public Point(string s)
   {
      Point result;

      if (TryParse(s, out result))
      {
         this.x = result.x;
         this.y = result.y;
      }
      else
      {
         throw new System.ArgumentException("cant parse");
      }
   }

   private Point(float x,float y) // for the sake of the example, this wouldnt have any use as public
   {
      this.x = x;
      this.y = y;
   }

   public static bool TryParse(string s,out Point result)
   {
      var numbers = s.Split(',');

      if(numbers.Length == 2)
      {
         result = new Point(float.Parse(numbers[0]),float.Parse(numbers[0]));
         return true;
      }
      else
      {
         result = null;
         return false;
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

您当前的方法并不真正起作用 - 因为float.Parse可以抛出异常.我会用以下的东西:

public static bool TryParse(string s, out Point result)
{
   var numbers = s.Split(',');
   if (numbers.Length == 2)
   {
       float x, y;
       if (float.TryParse(numbers[0], out x) && 
           float.TryParse(numbers[1], out y))
       {
           result = new Point(x, y);
           return true;  
       }    
   }
   result = null;
   return false;
}
Run Code Online (Sandbox Code Playgroud)

正如StriplingWarrior所说,我将摆脱解析构造函数开始 - 如果你还在使用TryParse,Parse也要添加一个方法.

两个构造函数的想法,加上必须将try解析的结果复制到解析构造函数中的只读字段,这有点令人闻到.

使用这种方法,您只需要一个构造函数 - 但是将值传递给构造函数并将它们复制到对象中会出现什么问题?这对我来说似乎很自然.

或者,您可以使用我们在Noda Time中使用的方法,您可以在其中创建一个负责解析和格式化的完整单独对象,以及一种ParseResult<T>能够表示解析成功/失败的类型,同时保留抛出异常的能力.关于失败的有意义的信息.就个人而言,我发现它比BCL模式好很多,虽然可以说我有偏见:)