我有一个Address对象,它具有AddressLine1,AddressLine2,Suburb,State,ZipCode属性。 (还有更多,但这足以作为例子)。此外,这些属性中的每一个都是字符串。我正在使用C#3.0。
我想把它表示为一个字符串,但正如我所做的那样,我发现由于所有的if语句,我正在创建一个具有高圈复杂度的方法......
假设分配给每个属性的字符串与属性的名称相同(即AddressLine1 =“AddressLine1”)...我希望地址表示如下:
“AddressLine1 AddressLine2 Suburb State ZipCode”。
现在,我这样做的原始方式是一个简单的String.Format()
String.Format("{0} {1} {2} {3} {4}", address.AddressLine1,
address.AddressLine2, address.Suburb, address.State, address.ZipCode);
这一切都很好,直到我发现其中一些字段可以为空...特别是AddressLine2。结果是额外的不需要的空间......当你连续几个时,这特别令人讨厌。
为了解决这个问题,以及我能想到的唯一解决方案,我必须手动构建字符串,只有在字符串不为空或空时才将地址属性添加到字符串中。
即
string addressAsString = String.Empty;
if (!String.IsNullOrEmpty(address.AddressLine1))
{
addressAsString += String.Format("{0}", address.AddressLine1);
}
if(!String.IsNullOrEmpty(address.AddressLine2))
{
addressAsString += String.Format(" {0}", address.AddressLine2);
}
etc....
有没有更优雅和/或简洁的方法来实现这一点,我没有想到?我的解决方案只是感觉凌乱和臃肿...但我想不出更好的方法来做到这一点......
就我所知,鉴于我想做的事情,这是我唯一的选择......但我只是想把它扔出去看看有没有比我更有经验的人知道更好的方法。如果没有更好的选择,那么哦......但如果有,那么我将学到一些我以前不知道的东西。
提前致谢!
答案 0 :(得分:3)
这可能不是最有效的方式,但它很简洁。您可以将所需的项目放入数组中并过滤掉没有重要值的项目,然后加入它们。
var items = new[] { line1, line2, suburb, state, ... };
var values = items.Where(s => !string.IsNullOrEmpty(s));
var addr = string.Join(" ", values.ToArray());
可能更高效,但更难阅读,将值汇总为StringBuilder
,例如
var items = new[] { line1, line2, suburb, state, ... };
var values = items.Where(s => !string.IsNullOrEmpty(s));
var builder = new StringBuilder(128);
values.Aggregate(builder, (b, s) => b.Append(s).Append(" "));
var addr = builder.ToString(0, builder.Length - 1);
我可能倾向于像第一个实现一样,因为它更简单,更易于维护的代码,然后如果性能是一个问题,考虑更像第二个实现(如果它确实变得更快......) )。
(注意这需要C#3.0,但你没有提到你的语言版本,所以我假设这没问题。)
答案 1 :(得分:1)
将字符串放在一起时,我建议您使用StringBuilder类。原因是System.String是不可变的,因此您对字符串所做的每个更改都只返回一个新字符串。
如果要在文本中表示对象,最好覆盖ToString()方法并将实现放在那里。
最后但并非最不重要的是,使用C#3.5中的Linq,您可以像Greg Beech一样加入这些,但不是使用string.Join()使用:
StringBuilder sb = new StringBuilder();
foreach (var item in values) {
sb.Append(item);
sb.Append(" ");
}
希望这有帮助。
答案 2 :(得分:1)
我建议覆盖ToString方法,并采用定义自定义类型的IFormatProvider实现。
有关实施IFormatProvider的信息,请参阅http://msdn.microsoft.com/en-us/library/system.iformatprovider.aspx上的MSDN。
然后您可以编写如下代码:
address.ToString( “S”); //简短地址
address.ToString( “任何”); //您定义的任何自定义格式。
绝对不是最简单的方法,但最干净的恕我直言。这种实现的一个例子是DateTime类。
干杯
灰
答案 3 :(得分:0)
首先,地址需要某些信息,所以你不应该允许一个没有邮政编码的地址。您还可以通过将每个属性初始化为空字符串,或者通过要求每个属性作为构造函数的参数来确保它们永远不为null。这样您就知道您正在处理有效数据,因此您只需输出格式化字符串,而无需进行IsNullOrEmpty检查。
答案 4 :(得分:0)
我有一个类似的问题,建立一个可能有几个空字段的多行联系人摘要。我几乎做了同样的事情,除了我使用字符串构建器,因为不能一遍又一遍地连接到字符串。
答案 5 :(得分:0)
如果您的数据不完全可靠,您需要在某处使用该逻辑 - 我建议您创建另一个只读属性(称为FormattedAddress),为您执行该逻辑。这样,您不必更改任何代码,在某些时候,您需要清理或更改规则。
+1表示使用stringbuilder的建议,而不是连接字符串。
答案 6 :(得分:0)
我知道这确实很老,但是我感觉到了一个通用的解决方案并以这种方式实现了我的方法:
private static string GetFormattedAddress(
string address1,
string address2,
string city,
string state,
string zip)
{
var addressItems =
new []
{
new[] { address1, "\n" },
new[] { address2, "\n" },
new[] { city, ", " },
new[] { state, " " },
new[] { zip, null }
};
string suffix = null;
var sb = new StringBuilder(128);
foreach (var item in addressItems)
{
if (!string.IsNullOrWhiteSpace(item[0]))
{
// Append the last item's suffix
sb.Append(suffix);
// Append the address component
sb.Append(item[0]);
// Cache the suffix
suffix = item[1];
}
}
return sb.ToString();
}