2015-09-07 38 views
4

創建RegionInfo上市適用於文化的給定區域,這是我當前的代碼:一個比較文化區,而不從LCID

public IEnumerable<CultureInfo> ForRegion(RegionInfo regionInfo) 
{ 
    return CultureInfo.GetCultures(CultureTypes.SpecificCultures) 
      .Where(c => Equals(new RegionInfo(c.LCID), regionInfo)); 
} 

,但我不喜歡在Where創建RegionInfo

我真的想要做的事是:

public IEnumerable<CultureInfo> ForRegion(RegionInfo regionInfo) 
{ 
    return CultureInfo.GetCultures(CultureTypes.SpecificCultures) 
      .Where(c => c.LCID == regionInfo.LCID); 
} 

但是因爲沒有對RegionInfoLCID我不能。除了更好的解決方案之外,知道爲什麼RegionInfo沒有LCID會很有趣。

試驗例:

[TestMethod] 
public void Can_find_all_by_region_ES_valencia() 
{ 
    var regionInfo = new RegionInfo(new CultureInfo("ca-ES-valencia").LCID); 
    List<CultureInfo> found = ForRegion(regionInfo).ToList(); 
    Assert.AreEqual(5, found.Count); 
    CollectionAssert.AreEqual(
     new[] 
     { 
      new CultureInfo("ca-ES"), 
      new CultureInfo("ca-ES-valencia"), //missing with Jon's solution 
      new CultureInfo("es-ES"), 
      new CultureInfo("eu-ES"), 
      new CultureInfo("gl-ES") 
     }, 
     found); 
} 

這適用於我目前的解決方案,但不是喬恩的。

另外兩個試驗,失敗了喬恩的修改的方案(原創作品):

[TestMethod] 
public void Can_find_all_by_region_Germany() 
{ 
    List<CultureInfo> found = ForRegion(new RegionInfo("DE")).ToList(); 
    Assert.AreEqual(3, found.Count); 
    CollectionAssert.AreEqual(
     new[] {new CultureInfo("de-DE"), new CultureInfo("dsb-DE"), new CultureInfo("hsb-DE")}, found); 
} 

[TestMethod] 
public void Round_trip_all_cultures() 
{ 
    foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures)) 
     Assert.IsTrue(ForRegion(new RegionInfo(culture.LCID)).Contains(culture), culture.Name); 
} 
+1

比爾布萊森: 「語言是與軍隊和海軍方言」。 –

回答

0

正如Jon Skeet指出的,RegionInfo s通過Name進行比較。當您從LCID創建RegionInfo時,該名稱實際上來自LCID找到的CultureData上的一個屬性。

所以我添加了一個有效的擴展方法(至少我的目的,即在我的解決方案中,我需要創建每個區域一次),從文化中獲取區域名稱。

public static class CultureInfoExtension 
{ 
    private static readonly Dictionary<int, string> RegionNamesByLcid = 
     CultureInfo.GetCultures(CultureTypes.SpecificCultures) 
      .Select(c => c.LCID) 
      .Distinct() 
      .ToDictionary(lcid => lcid, lcid => new RegionInfo(lcid).Name); 

    private static string FallbackToThrowConsistentException(CultureInfo c) 
    { 
     return new RegionInfo(c.LCID).Name; 
    } 

    public static string GetRegionName(this CultureInfo c) 
    { 
     string name; 
     return RegionNamesByLcid.TryGetValue(c.LCID, out name) 
      ? name 
      : FallbackToThrowConsistentException(c); 
    } 
} 

用法:

public IEnumerable<CultureInfo> ForRegion(RegionInfo regionInfo) 
{ 
    return CultureInfo.GetCultures(CultureTypes.SpecificCultures) 
     .Where(c => CultureBelongsToRegion(c, regionInfo)); 
    } 

    private static bool CultureBelongsToRegion(CultureInfo c, RegionInfo regionInfo) 
    { 
     return c.GetRegionName() == regionInfo.Name; 
    } 
} 
4

這應該是從你從查詢得到的結果相當明顯 - 在同一區域可以有多個語言環境(從而,LCID)。所以最好的情況是,你可以得到一個給定地區的LCID列表列表 - 如果你想維護這個列表,只需自己製作。

例如,區域GB(英國)是家裏三個不同的語言環境 - cy-GB(1106),gd-GB(1169)和en-GB(2057)。

只要表現良好,除非你可以避免所有分配在你的Where,沒有太多的調整。即使是一個簡單的string.Split將可能花費你比簡單做new RegionInfo更多。文化數據被緩存,所以在第一次之後只有與這種操作相關的內存成本。當然,如果你不介意記憶成本,沒有什麼能夠阻止你建立自己的查詢。

+0

是的,現在你明白了! – weston