劇透:遺留代碼、C#、.NET 4.52
我正在尋找替代解決方案來比較兩個不同的列舉值,它們在不同的專案中以不同的順序宣告,但含義和名稱相同。LikeEnumDecl1.FirstName的含義相同,EnumDecl2.FirstName但它們的底層值不同(它們在不同的專案中由不同的作業組宣告,但通過 Web 服務相互通信)。
在整個現有代碼庫中,他們基本上使用以下代碼:
if(var1.ToString().Equals(EnumDecl2.FirstName.ToString()
|| var1.ToString().Equals(EnumDecl2.SecondName.ToString())
在某些情況下,呼叫ToUpper/ToLower使事情變得更有趣。現在用一種方法進行幾十次比較,你就會發現一只昆蟲爬過路障。
列舉上的 Equals() 不能被覆寫或擴展,因此您可以提出哪些其他建議來改進比較(忽略,var1.ToString()因為這可以放入變數中)。
這是 15 年以上的代碼,分布在龐大的代碼庫中。我正在尋找逐漸改進它的方法。
uj5u.com熱心網友回復:
您可以結合擴展方法的想法和Dictionary
public static class FirstTypeEnumExtensions
{
private static Dictionary<FirstTypeEnum, SecondTypeEnum> _firstTypeToSecondTypeMap = new Dictionary<FirstTypeEnum, SecondTypeEnum>
{
{FirstTypeEnum.First, SecondTypeEnum.First},
{FirstTypeEnum.Second, SecondTypeEnum.Second},
{FirstTypeEnum.Third, SecondTypeEnum.Third}
};
public static bool IsEquivalentTo(this FirstTypeEnum first, SecondTypeEnum second)
{
var success = _firstTypeToSecondTypeMap.TryGet(first, out var mappedSecond);
if (!success)
throw new ArgumentException($"{nameof(FirstTypeEnum)} {first} does not have a mapping defined to {nameof(SecondTypeEnum)}", nameof(first));
return mappedSecond == second;
}
}
使用擴展時,它看起來像這樣
if (firstType.IsEquivalentTo(secondType))
{
...
}
具有自動填充地圖和雙向擴展的更新解決方案
Dictionary<int, int> map1 = new Dictionary<int, int>();
Dictionary<int, int> map2 = new Dictionary<int, int>();
// build the maps
foreach(var e1 in Enum.GetValues(typeof(EnumDecl1)))
map1.Add((int)e1, ((int)Enum.Parse<EnumDecl2>(e1.ToString())));
foreach(var e2 in Enum.GetValues(typeof(EnumDecl2)))
map2.Add((int)e2, ((int)Enum.Parse<EnumDecl1>(e2.ToString())));
// extension methods to compare them both ways
public static bool Is(this EnumDecl1 first, EnumDecl2 second)
{
var success = map2.TryGetValue((int)second, out var mappedSecond);
return success && (mappedSecond == (int)first);
}
public static bool Is(this EnumDecl2 first, EnumDecl1 second)
{
var success = map1.TryGetValue((int)second, out var mappedSecond);
return success && (mappedSecond == (int)first);
}
uj5u.com熱心網友回復:
我的解決方案是,當需要特定型別的值時,進行轉換并執行必要的操作。
例如,我EnumTeamA有價值,但我需要呼叫帶EnumTeamB引數的函式。轉換是必要的。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
public enum EnumTeamA
{
First = 1,
Second = 2,
Third = 3,
Fourth = 4,
Fifth = 5
}
public enum EnumTeamB
{
A = 100,
B = 200,
C = 300,
D = 400,
E = 500
}
public static class EnumExtensions
{
private static ReadOnlyDictionary<EnumTeamA, EnumTeamB> TeamADictionary = new ReadOnlyDictionary<EnumTeamA, EnumTeamB>(new Dictionary<EnumTeamA, EnumTeamB>
{
{ EnumTeamA.First, EnumTeamB.A},
{ EnumTeamA.Second, EnumTeamB.B},
{ EnumTeamA.Third, EnumTeamB.C},
{ EnumTeamA.Fourth, EnumTeamB.D},
{ EnumTeamA.Fifth, EnumTeamB.E}
});
private static ReadOnlyDictionary<EnumTeamB, EnumTeamA> TeamBDictionary = new ReadOnlyDictionary<EnumTeamB, EnumTeamA>(new Dictionary<EnumTeamB, EnumTeamA>
{
{ EnumTeamB.A, EnumTeamA.First},
{ EnumTeamB.B, EnumTeamA.Second},
{ EnumTeamB.C, EnumTeamA.Third},
{ EnumTeamB.D, EnumTeamA.Fourth},
{ EnumTeamB.E, EnumTeamA.Fifth}
});
public static EnumTeamB Convert(this EnumTeamA key)
{
EnumTeamB value;
bool ok = TeamADictionary.TryGetValue(key, out value);
return ok ? value : throw new NotImplementedException("Invalid enum value: " key.GetType().FullName);
}
public static EnumTeamA Convert(this EnumTeamB key)
{
EnumTeamA value;
bool ok = TeamBDictionary.TryGetValue(key, out value);
return ok ? value : throw new NotImplementedException("Invalid enum value: " key.GetType().FullName);
}
}
public static class Program
{
public static void FunctionThatNeedsEnumTeamA(EnumTeamA value)
{
// Your custom code
}
public static void FunctionThatNeedsEnumTeamB(EnumTeamB value)
{
// Your custom code
}
public static void Main()
{
// Context 1 - You have EnumTeamA value but need to call a function with EnumTeamB value.
EnumTeamA enumTeamAValue = EnumTeamA.Fourth;
FunctionThatNeedsEnumTeamB(enumTeamAValue.Convert());
// Context 2 - You have EnumTeamB value but need to call a function with EnumTeamA value.
EnumTeamB enumTeamBValue = EnumTeamB.D;
FunctionThatNeedsEnumTeamA(enumTeamBValue.Convert());
Console.ReadLine();
}
}
uj5u.com熱心網友回復:
一種方法是使用字典。例如,如果我們有以下兩個列舉:
enum Enum1 { Value1, Value2, Value3 }
enum Enum2 { Value3, Value1, Value2 }
...我們可以這樣寫:
// You probably want to declare this globally and instantiate only once.
var enumDictionary = new Dictionary<Enum1, Enum2>
{
{ Enum1.Value1, Enum2.Value1 },
{ Enum1.Value2, Enum2.Value2 },
{ Enum1.Value3, Enum2.Value3 }
};
// Create a bogus value of Enum1.
Enum1 e1 = GetEnum1();
// Get the corresponding Enum2 value.
Enum2 e2 = enumDictionary[e1];
uj5u.com熱心網友回復:
你可以先做一個方法:
public bool IsEqual(EnumDecl1 enumDec1, EnumDecl2 enumDec2)
{
return enumDec1.ToString() == enumDec2.ToString() ? true : false;
}
并呼叫給出您要檢查的 2 個值的方法。
if(IsEqual(EnumDecl1.FirstName,EnumDecl2.SecondeName))
{
do something...
}
uj5u.com熱心網友回復:
您可以使用 switch 陳述句。
enum Enum1 { Value1, Value2, Value3 }
enum Enum2 { Value3, Value2, Value1 }
switch (enum1)
{
case Enum1.Value1:
return enum2 == Enum2.Value1;
case Enum1.Value2:
return enum2 == Enum2.Value2;
case Enum1.Value3:
return enum2 == Enum2.Value3;
default:
return false;
}
我唯一要注意的是,如果您計劃向任一列舉添加值,這可能會導致問題,因為您還需要記住更新此開關....
uj5u.com熱心網友回復:
由于這些不同的專案通過 Web 服務進行通信,我將通過以下方式解決這樣的問題:
確定您最終希望將整個代碼庫移動到的列舉的規范定義。你可能實際上永遠不會到達那里,但有一個目標是件好事。
對于單個專案,請確保無論何時從 Web 服務獲取資料,都立即將相關值映射到規范列舉。在那個專案中,您永遠不會將這些列舉轉換為字串(除非您出于某種原因需要顯示它們)。您可以直接比較列舉。如果您需要將資料發送到另一個 Web 服務,請將列舉映射到 Web 服務期望的值。
當您需要更新另一個專案時,請確保列舉定義與您的規范列舉匹配,并對輸入和輸出執行相同的操作。如果您已經使用整個代碼庫完成此操作,您可以將列舉定義移動到共享專案中,以便更容易維護兼容性,并且您可以擺脫所有映射代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/446778.html
上一篇:Gem::Ext::BuildError:錯誤:無法在macOSMonterey上構建gem原生擴展
下一篇:宣告DI物件的最佳方式
