Can I make an alias for enum value name in C# ?
For example I have two files: A and B.
public class A
{
public enum myEnum
{
value_1,
value_2
};
}
And I want to use this enum in B class:
public class B
{
private A.myEnum[] tab = { A.myEnum.value_1, A.myEnum.value_2, A.myEnum.value_1 ..}
}
I want to make an alias for:
A.myEnum.value_1 and A.myEnum.value_2
so I could write
private A.myEnum[] tab = { alias_1, alias_2},
I think I might be missing something, but:
public class B
{
private const A.myEnum alias_1 = A.myEnum.value_1;
private const A.myEnum alias_2 = A.myEnum.value_2;
private A.myEnum[] tab = {alias_1, alias_2};
}
Using a helper method like
public static myEnum GetEnumName(string str)
{
switch(str)
{
case "alias_1": return myEnum.Value_1;
case "alias_2": return myEnum.Value_2;
default: throw new Exception();
}
}
You just could get all the values and turn them into an array:
myEnum[] tab = Enum.GetValues(typeof(myEnum)).Cast<myEnum>().ToArray();
Related
I am trying to create some sort of mapping and construct a switch statement based on this.
The first thing I tried was this:
public class Class1
{
public void Test()
{
string testString_A = "A";
string testString_B = null;
switch (testString)
{
case Options.O1.aName:
testString_B = Options.O1.bName;
break;
case Options.O2.aName:
testString_B = Options.O2.bName;
break;
}
}
}
public static class Options
{
public static Option O1 = new Option()
{
aName = "A1",
bName = "B1"
};
public static Option O2 = new Option()
{
aName = "A2",
bName = "B2"
};
}
public class Option
{
public string aName;
public string bName;
}
In this scenario, compiler complains that a constant value is expected for the switch cases.
So next, I tried the following but it does not work either. The .aName I try to use in the switch statement seems not accessible.
public Class1()
{
public void Test()
{
string testString = "A1";
switch (testString)
{
case Options.O1.aName:
...
}
}
}
public static class Options
{
public static Option_O1 O1 = new Option_O1();
public static Option_O2 O2 = new Option_O2();
}
public class Option_O1
{
public const string aName = "A1";
public const string bName = "B1";
}
public class Option_O2
{
public const string aName = "A2";
public const string bName = "B2";
}
How can I accomplish what I want?
There's a big difference between a string property / field variable (even if it is static or readonly), and a const string. The switch statement requires either literals, or const values in the case statements.
This explains why your first attempt didn't succeed (Error : "A Constant value is required").
In the second case, although you could obviously do this:
switch (testString)
{
case Option_O1.aName:
return Option_O1.bName;
case Option_O2.aName:
return Option_O2.bName;
}
but as soon as you try and 'cheat' the constant switch requirement by introducing the static class container, you're back to the same problem, although a more cryptic compiler error:
case Options.O1.aName: // Cannot be accessed by an instance reference
return Option_O1.bName;
Alternative to switch
I'm guessing here, but it seems that you need to build a run time mapping function.
Assuming that you always want to return the same data type (a string), I would suggest using a Dictionary keyed by the string you are trying to 'switch' on - this mapping can be built up at run time.
Here's an example of a statically bootstrapped map:
public static class Options
{
public static Option O1 = new Option()
{
aName = "A1",
bName = "B1"
};
public static Option O2 = new Option()
{
aName = "A2",
bName = "B2"
};
}
private static IDictionary<string, Option> myOptionMap = new []
{
Options.O1, Options.O2
}
.ToDictionary(x => x.aName);
Which you can use like so:
public string Test(string someAName)
{
if (myOptionMap.TryGetValue(someAName, out var myOption))
{
return myOption.bName;
}
// Oops not found
return string.Empty;
}
Unless there's more to this than your MVP, it's unlikely that you'll want to subclass your options per instance - Option_O1
public EnumA
{
name = 1,
surname = 2
}
public EnumB
{
name = 50,
surname = 60
}
public void myMethod(User u,Enum e)
{
//Enum e can be either EnumA or EnumB
//Do something with the Enum Passed
}
Let's say I have the above code but instead of specifiying the Enum in the method like I'm doing above, I'd like to select the enum which is passed through the method parameter. Is there any way of doing so?
You can do this via reflection, but I'm worried that you don't understand enumerations properly. It kind of looks to me like you are trying to use them as class instances to hold arbitrary data, in which case, you really should be using a real class.
In case I'm wrong, I've included code below to do what you are asking for, but I don't think it will be very useful for you.
void Main()
{
Test(EnumA.First);
Console.WriteLine("-----");
Test(EnumB.B);
}
void Test(Enum theEnum)
{
Type t = theEnum.GetType();
foreach (string element in Enum.GetNames(t))
{
Debug.WriteLine(element + " = " + (int) Enum.Parse(t, element));
}
}
enum EnumA
{
First = 1,
Second = 2
}
enum EnumB
{
A = 1,
B = 2,
C = 3
}
It generates the following output:
First = 1
Second = 2
-----
A = 1
B = 2
C = 3
I think this is more what you are trying to do though:
void Main()
{
Person A = new Person()
{
Name = "John",
Surname = "Doe"
};
Person B = new Person()
{
Name = "Jane",
Surname = "Doe"
};
A.ShowInfo();
Console.WriteLine("----");
B.ShowInfo();
}
class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public void ShowInfo()
{
Debug.WriteLine("Name=" + Name);
Debug.WriteLine("Surname=" + Surname);
}
}
It output the following:
Name=John
Surname=Doe
----
Name=Jane
Surname=Doe
Have you tried the following:
public void myMethod(User u,Enum e)
{
if (e is EnumA)
{
EnumA ea = (EnumA)e;
// Do something with ea
}
else if (e is EnumB)
{
EnumB eb = (EnumB)e;
...
}
}
you have use generic type for this operation.
below code is showing a sample code (as Console app);
class Program
{
static void Main(string[] args)
{
myMethod<EnumA>("deneme", EnumA.name);
}
public enum EnumA
{
name = 1,
surname = 2
}
public enum EnumB
{
name = 50,
surname = 60
}
public static void myMethod<T>(string u, T e)
where T : struct,IConvertible
{
if (typeof(T) == typeof(EnumA))
{
Console.WriteLine("EnumA");
}
else if (typeof(T) == typeof(EnumB))
{
Console.WriteLine("EnumB");
}
Console.ReadLine();
}
}
You could use overloading:
public void myMethod(User u, EnumA e)
{
// Call a function common to both
}
public void myMethod(User u, EnumB e)
{
// Call a function common to both
}
I guess C# 7.3 allows you to do something like:
public void myMethod(User u, TEnum e) where TEnum : Enum
{
//Enum e can be either EnumA or EnumB
//Do something with the Enum Passed
}
I used something like this for a pre-7.3 project and it was a little ugly, but WAY better and more readable than any other way I could find:
public void myMethod(User u, object e)
{
// Test to make sure object type is either EnumA or EnumB
// Call a function common to both
// object e can be either EnumA or EnumB by casting like ((EnumA)e) or ((EnumB)e)
}
This is not how enums behave (or should behave). You're basically creating two different instances of enums. This is why classes exist in C#. Consider creating a class:
public class SomeEnum
{
public int Name;
public int Surname;
private SomeEnum(int name, int surname)
{
Name = name;
Surname = surname;
}
public static SomeEnum EnumA => new SomeEnum(1, 2);
public static SomeEnum EnumB => new SomeEnum(50, 60);
}
And changing your method to this:
public void myMethod(User u, SomeEnum e)
{
// Enum e can be either EnumA or EnumB
// Do something with the Enum passed
}
I changed as least code as possible as I'm not sure what the purpose is of these 'Enums', but this way you'll be able to create as many instances as you want, without your code getting messy with all of these identical Enum specifications.
To use this method with EnumA for example you can call myMethod(user, SomeEnum.EnumA).
This way it's only possible to use the specified enums (EnumA and EnumB). Alternatively, if you want to create enums on-the-fly, the code can be changed to:
public class SomeEnum
{
public int Name;
public int Surname;
public SomeEnum(int name, int surname)
{
Name = name;
Surname = surname;
}
}
This way you can call the method with myMethod(user, new SomeEnum(1, 2)).
I'm developing a class which contains some const strings
public static class Constants
{
public const string CarID= "car_id";
//public const string NumberID= "number_id"; // this is the second const string might be added, so
//the new created function can return the two
}
public class CarENParameters
{
public string Params { get; set; }
public CarENParameters(string carId)
{
Params = carId;
}
}
public static class CarPropertyProcess
{
//test params
public static CarENProps Parse(Uri uri,string content)
{
string carID= Regex.Matches(content, #"\$\('#CarXL'\)\.val\((\d+)\)", RegexOptions.None)[0].Groups[1].Value;
var parameters = new Dictionary<string, string>
{
{Constants.CarID, carID},
};
return new CarENProps(uri.AbsoluteUri, parameters);
}
public static CarENParameters GetParameters()
{
return new CarENParameters(Constants.CarID);
}
}
In the class Constants, I have one carID, now the case is it might have more than one const string like : public const string NumberID= "number_id";
So I want to create one function to return a list of those const strings, which are car_id and number_id with a class name CarENParameters but I havent figured out how to return a list by a get/set in a class, should I use dictionary or keyvaluespair to achieve that ? I'm quite new to C# so hope that I can have a better point of view from the helps of you guys. Thanks
Are you looking for something like this:
public static List<CarENParameters> GetParameters()
{
return new List<CarENParameters>()
{
new CarENParameters(Constants.CarID1),
new CarENParameters(Constants.CarID2),
new CarENParameters(Constants.CarID3)
}
}
You can use reflection for this
don't forget to put using System.Reflection;
// get class type
Type type = typeof(Constants);
// get a list of fields
FieldInfo[] fields = type.GetFields();
List<CarENParameters> list = new List<CarENParameters>();
// loop on field list
foreach (FieldInfo field in fields)
{
// if field is a string add it to our return list
if (field.FieldType == typeof(String))
list.Add(new CarENParameters((String) field.GetValue(null)));
}
I would like an advice. My project have a lot of equals methods with different values, and i would like to do a single method that does the same.
The methods are this:
private void Enum1()
{
Console.WriteLine(Enum.GetValue(ENUM1.Code));
Console.WriteLine(Enum.GetValue(ENUM1.Info));
}
private void Enum2()
{
Console.WriteLine(Enum.GetValue(ENUM2.Code));
Console.WriteLine(Enum.GetValue(ENUM2.Info));
}
private void Enum3()
{
Console.WriteLine(Enum.GetValue(ENUM3.Code));
Console.WriteLine(Enum.GetValue(ENUM3.Info));
}
This is the enums:
public enum ENUM1
{
Code = 1,
Info = 3
}
public enum ENUM2
{
Code = 91,
Info = 4
}
public enum ENUM3
{
Code = 6,
Info = 27
}
There is only a way to create a method by inserting the input type of enum to use? maybe a similar solution of this:
private void General("ENUM1")
{
var type = ENUM1;
switch (p)
{
case "ENUM1":
type = ENUM1;
case "ENUM2":
type = ENUM2;
case "CASALINGHI":
type = ENUM3;
default:
type = ENUM1;
}
Console.WriteLine(Enum.GetValue(type.Code));
Console.WriteLine(Enum.GetValue(type.Info));
}
I think something like this is what you are looking for:
private void General<T>()
{
var values = Enum.GetValues(typeof(T));
foreach(var value in values)
Console.WriteLine(value);
}
General<Enum1>();
General<Enum2>();
General<Enum3>();
Or this, depending on how you want to use it:
private void General(Type enumType)
{
var values = Enum.GetValues(enumType);
foreach(var value in values)
Console.WriteLine(value);
}
General(typeof(Enum1));
General(typeof(Enum2));
General(typeof(Enum3));
Why do you keep using enums, when you can easily use classes? Read more about Object-Oriented programming.
Create a single class:
public class MyEnum
{
public int Code
{
get; set;
}
public int Info
{
get; set;
}
public string Display()
{
Console.WriteLine(this.Code);
Console.WriteLine(this.Info)
}
//
// This will keep your enums static, available from any method
//
private static List<MyEnum> _globals = new List<MyEnum();
public static List<MyEnum> Globals ()
{
if (this._globals.Count == 0)
{
this._globals.Add(new MyEnum(){ Code = 1, Info = 3 });
this._globals.Add(new MyEnum(){ Code = 91, Info = 4 });
this._globals.Add(new MyEnum(){ Code = 6, Info = 27 });
}
return this._globals;
}
}
After this you can easily print out all the enums with the following code:
foreach (MyEnum* en in MyEnum.Globals())
{
en.Display();
}
Please look into solutions similar to this one, since your enum's obviously represent some data.
i need an enum or something similiar to do something like this:
public enum MyStringEnum {
[StringValue("Foo A")] Foo = "A",
[StringValue("Foo B")] Foo = "B" }
is this possible? my example, i return back a dataset with a value represented as either A,B,C,D,E .. i need a solution to return this as a string representation?
i guess the obvious would be to create an extension method or something which just had a switch statement in and return a string .. any other cleaner solutions?
regards,
dave
Here is something we use for our MVC applications to retrieve a display name for our enums. It uses a custom attribute and an extension method to retrieve the enum display name.
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EnumDisplayNameAttribute : Attribute
{
public EnumDisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
public string DisplayName { get; set; }
}
public static string GetDisplayName(this Enum enumType)
{
var displayNameAttribute = enumType.GetType()
.GetField(enumType.ToString())
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
.FirstOrDefault() as EnumDisplayNameAttribute;
return displayNameAttribute != null ? displayNameAttribute.DisplayName : Enum.GetName(enumType.GetType(), enumType);
}
Usage on the enum:
public enum Foo
{
[EnumDisplayName("Foo Bar")]
Bar = 0
}
Getting back the display name:
var f = Foo.Bar;
var name = f.GetDisplayName();
Would it be an option not to use enum and use structs instead?
struct FooEnum
{
private int value;
private string name;
private FooEnum(int value, string name)
{
this.name = name;
this.value = value;
}
public static readonly FooEnum A = new FooEnum(0, "Foo A");
public static readonly FooEnum B = new FooEnum(1, "Foo B");
public static readonly FooEnum C = new FooEnum(2, "Foo C");
public static readonly FooEnum D = new FooEnum(3, "Foo D");
public override string ToString()
{
return this.name;
}
//TODO explicit conversion to int etc.
}
You could then use FooEnum like an enum with an own ToString() overload:
FooEnum foo = FooEnum.A;
string s = foo.ToString(); //"Foo A"
If you want to do something like this:
MyStringEnum value = MyStringEnum.A;
string description = value.GetDescription();
// description == "Foo A"
Setup your enum like this:
public enum MyStringEnum
{
[Description("Foo A")]
A,
[Description("Foo B")]
B
}
And use a utility/extension method that reads the attribute:
public static string GetDescription(this MyStringEnum enumerationValue)
{
Type type = enumerationValue.GetType();
string name = enumerationValue.ToString();
//Tries to find a DescriptionAttribute for a potential friendly name for the enum
MemberInfo[] member = type.GetMember(name);
if (member != null && member.Length > 0)
{
object[] attributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attributes[0]).Description;
}
}
return name;
}
I've seen this done where I would put
MyStringEnum.Foo.ToString();
In this case it would give "A"
The cleanest solution for this problem is to create a custom attribute that will store the string value you want for the enum constant. I've used that strategy in the past and it worked out fairly well. Here's a blog post detailing the work involved:
Enum With String Values In C# - Stefan Sedich's Blog
Of course this is only necessary if you need some kind of meaningful text. If the name of the enum constant works for you...then you can simply call ToString().