Nach der Antwort von @Even Mien habe ich versucht, ein bisschen weiter zu gehen und es generisch zu machen, ich scheine fast am Ziel zu sein, aber ein Fall sträubt sich noch und ich kann wahrscheinlich meinen Code ein bisschen vereinfachen.
Ich poste es hier, wenn jemand sehen, wie ich verbessern könnte und vor allem machen es funktioniert, da ich nicht zuweisen kann es von einer Zeichenfolge
Bisher habe ich die folgenden Ergebnisse:
Console.WriteLine(TestEnum.Test1);//displays "TEST1"
bool test = "TEST1" == TestEnum.Test1; //true
var test2 = TestEnum.Test1; //is TestEnum and has value
string test3 = TestEnum.Test1; //test3 = "TEST1"
var test4 = TestEnum.Test1 == TestEnum.Test2; //false
EnumType<TestEnum> test5 = "TEST1"; //works fine
//TestEnum test5 = "string"; DOESN'T compile .... :(:(
Wo die Magie geschieht:
public abstract class EnumType<T> where T : EnumType<T>
{
public string Value { get; set; }
protected EnumType(string value)
{
Value = value;
}
public static implicit operator EnumType<T>(string s)
{
if (All.Any(dt => dt.Value == s))
{
Type t = typeof(T);
ConstructorInfo ci = t.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,null, new Type[] { typeof(string) }, null);
return (T)ci.Invoke(new object[] {s});
}
else
{
return null;
}
}
public static implicit operator string(EnumType<T> dt)
{
return dt?.Value;
}
public static bool operator ==(EnumType<T> ct1, EnumType<T> ct2)
{
return (string)ct1 == (string)ct2;
}
public static bool operator !=(EnumType<T> ct1, EnumType<T> ct2)
{
return !(ct1 == ct2);
}
public override bool Equals(object obj)
{
try
{
return (string)obj == Value;
}
catch
{
return false;
}
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public static IEnumerable<T> All
=> typeof(T).GetProperties()
.Where(p => p.PropertyType == typeof(T))
.Select(x => (T)x.GetValue(null, null));
}
Ich muss dies dann nur noch für meine Enums deklarieren:
public class TestEnum : EnumType<TestEnum>
{
private TestEnum(string value) : base(value)
{}
public static TestEnum Test1 { get { return new TestEnum("TEST1"); } }
public static TestEnum Test2 { get { return new TestEnum("TEST2"); } }
}
1 Stimmen
Mögliche Duplikate von Enum ToString
24 Stimmen
Ich bin mir nicht sicher, warum die meisten Antworten nicht einfach "const string" verwenden und stattdessen eigene Klassen erstellen.
2 Stimmen
Sie können zwar keine Zeichenketten verwenden, aber Sie können sehr wohl Zeichenketten verwenden. Das ist eine Option, wenn Sie Werte mit nur einem Buchstaben verwenden können.
2 Stimmen
Ich bin wirklich verwirrt, warum die oben von CTS_AE vorgeschlagene Lösung nicht einmal unter den ersten drei Antworten ist.
0 Stimmen
@Sinjai Die explizite Gruppierung zusammengehöriger Werte wiegt den Nachteil eines unmerklichen Leistungsverlusts auf, insbesondere bei einer API oder einer wiederverwendbaren Komponente.
0 Stimmen
Ich bin verwirrt. Während das Erstellen einer benutzerdefinierten Klasse, wie in der vorgeschlagenen Antwort vorgeschlagen, funktioniert, bin ich der Meinung, dass eine
const string
scheint der eigentliche Kandidat für dieses Problem zu sein. Ich würde es einfach halten.6 Stimmen
@Sau001 / CTS_AE - wollte dies hier anbringen, da diese Kommentare ganz oben stehen und man ein wenig scrollen muss, um die Antwort zu finden. Siehe den Kommentar von Pharap zu dieser Antwort: stackoverflow.com/a/5674697/5948647 . Statische Klassen können nicht als Methodenparametertypen verwendet werden, so dass Sie die Verwendung einer Ihrer vordefinierten konstanten Zeichenketten in Methoden nicht erzwingen können.