Finding an enum value by its Description Attribute [duplicate] - c#

This question already has answers here:
Get enum from enum attribute
(7 answers)
Closed 9 years ago.
This may seem a little upside down faced, but what I want to be able to do is get an enum value from an enum by its Description attribute.
So, if I have an enum declared as follows:
enum Testing
{
[Description("David Gouge")]
Dave = 1,
[Description("Peter Gouge")]
Pete = 2,
[Description("Marie Gouge")]
Ree = 3
}
I'd like to be able to get 2 back by supplying the string "Peter Gouge".
As a starting point, I can iterate through the enum fields and grab the field with the correct attribute:
string descriptionToMatch = "Peter Gouge";
FieldInfo[] fields = typeof(Testing).GetFields();
foreach (FieldInfo field in fields)
{
if (field.GetCustomAttributes(typeof(DescriptionAttribute), false).Count() > 0)
{
if (((DescriptionAttribute)field.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description == descriptionToMatch)
{
}
}
}
But then I'm stuck as to what to do in that inner if. Also not sure if this is the way to go in the first place.

Using the extension method described here :
Testing t = Enum.GetValues(typeof(Testing))
.Cast<Testing>()
.FirstOrDefault(v => v.GetDescription() == descriptionToMatch);
If no matching value is found, it will return (Testing)0 (you might want to define a None member in your enum for this value)

return field.GetRawConstantValue();
You could of course cast it back to Testing if required.

Ok, after typing all that I think this is a case of a decision right at the beginning leading me down the wrong path. Enum seemed the right way to go to start with, but a simple Dictionary<string, int> will suffice and be a hell of a lot easier to work with!

Related

Flags Enum.HasFlag not Working as Expected for Multiple bit fields [duplicate]

This question already has answers here:
How to check if any flags of a flag combination are set?
(18 answers)
Closed 1 year ago.
I have a list of records that contains a flags enum value. I am trying to filter on one or more value based on the flags supplied. The description of the HasFlag method is as follows:
true if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, false.
I would expect given an enum:
[Flags]
public enum MyFlaggedEnum
{
Unknown = 0,
First = 1,
Second = 2,
Third = 4,
Fourth = 8,
Fifth = 16,
Sixth = 32
}
And a record set containing a mixture of these values, assume that there are at least one record for each of the flags:
When I filter on one value:
var myFilteredList = MyMainList.Where(w => w.flagValue.HasFlag(MyFlaggedEnum.Third));
// myFilteredList returns the correct subset of records
When I filter on multiple values:
var myFilteredListMultiple = MyMainList.Where(w => w.flagValue.HasFlag(MyFlaggedEnum.First | MyFlaggedEnum.Fourth));
// myFilteredList returns an empty set
Am I misusing the HasFlag method; if so, how?
I am looking for a way to quickly filter the results so they can be displayed to the user in a datagridview based on filters they supply at runtime and can be changed at any time. I could loop through them or union multiple sets based on the flag filters requested by the user, but, was looking for a clean way.
EDIT: Whoever closed this question referring to this: How to check if any flags of a flag combination are set? does not understand the question. No, I am not adding First | Second values to my enum!!
I suggest that you eschew HasFlag and just do it directly using bit operations:
var myFilteredListMultiple = MyMainList.Where(w => (w.FlagValue & (MyFlaggedEnum.First | MyFlaggedEnum.Fourth)) != 0);
Or if you have a set of bitflags passed in called, say, mask:
var myFilteredListMultiple = MyMainList.Where(w => (w.FlagValue & mask) != 0);
There's an ambiguity over whether HasFlag should mean "has all" vs "has any"; it is implemented as "has all". But it is also an inefficient (boxing) API, so honestly: it is probably better to simply not use it. For example, you could add your own extension methods:
public static bool HasAny(this MyFlaggedEnum value, MyFlaggedEnum any)
=> (value & any) != 0;
public static bool HasAll(this MyFlaggedEnum value, MyFlaggedEnum all)
=> (value & all) == all;
and use .HasAny(MyFlaggedEnum.First | MyFlaggedEnum.Fourth)

C# property set if

Can I make a property in c# class that has no field, but I still can check the value and set it only if match?
I mean something like this:
public int Num
{
get;
set if value > 0 && value < 100;
}
I know that I can do this:
private int num;
public int Num
{
get
{
return num;
}
set
{
if (value > 0 && value < 100)
num = value;
}
}
But I want to do it without using a field, and just using property.
Is it possible?
To be clear: btw; it's not that the property won't be set to that value, it's just a different way to look at your question.
You can use attributes, but you'll need a way to validate them. For instance; the Range attribute:
[Range(0,100, ErrorMessage = "Value for {0} must be between {1} and {2}.")]
public int Num {get; set;}
So, this is typically used in MVC or EF like applications where the attributes are being checked by that particular framework.
There is some more info about that subject here: https://msdn.microsoft.com/en-us/library/cc668215(v=vs.110).aspx
It can also work in MVVM WPF applications, but again, you'll need a framework for that.
btw; it's not that the property won't be set to that value, it's just a different way to look at your question.
So if your use case is actually how to restrict and easily apply some business rules on a view or data-model, this is an accepted method. If you keep it to your original question can I do a conditional set without an if and a field?, the answer is no.
Some more attributes can be found here.
I think the answer is no. You may want to see this one and this one to know why.
Fields are ordinary member variables or member instances of a class. Properties are an abstraction to get and set their values.
by doing the first block, you just break shorthand that already defined in C# and if you want to implement that idea, I think #Stefan proposed a good one.

Getting Description from an array of Enums

I am trying to get the description from an array of enums bascically this is the current structure that I have.
public enum IllinoisNonDisclosureConvictionFormOptions
{
[Description("625 ILCS 5/11-501 - Driving Under the Influence")]
answerConviction0 = 0,
[Description("625 ILCS 5/11-503 - Reckless Driving")]
answerConviction1 = 1,
[Description("a violation of Article 11 of the Criminal Code of 1961, not including prostitution under 720 ILCS 5 / 11 - 14")]
answerConviction2 = 2,
[Description("720 ILCS 5/26-5 - Dog Fighting")]
answerConviction3 = 3,
[Description("720 ILCS 5/12-1 - Assault")]
answerConviction4 = 4,
}
So basically a user will select the crime they committed and then that text will be compared in a if statement to the description of the enums. What I currently have is this:
if (request.Question4 != null)
{
var answersForQuestion4 = Enum.GetValues(typeof(IllinoisNonDisclosureConvictionFormOptions)).Cast<IllinoisNonDisclosureConvictionFormOptions>().ToList();
foreach (Enum answer in answersForQuestion4)
{
//I need to compare the description to the selected text
string description = (enum description value)
if (request.Question4 == description)
{return description}
}
}
I may have to switch from enums to ControllersConstants since I dont really need to save their answers in the database. Please let me know if you have any insights regarding this matter.
This posted question (Get Enum from Description attribute) includes getting the enum description.
If you need the opposite and know that the responses MUST match your enum description, you can work backwards to get the enum using Max's answer.
The solution you posted seems to be looking for a matching enum name (e.g. answerConviction0) instead of a matching description as described in the question.
You can do something like this:
string findMe = "625 ILCS 5/11-503 - Reckless Driving";
Type enumType = typeof(IllinoisNonDisclosureConvictionFormOptions);
Type descriptionAttributeType = typeof(DescriptionAttribute);
foreach (string memberName in Enum.GetNames(enumType))
{
MemberInfo member = enumType.GetMember(memberName).Single();
string memberDescription = ((DescriptionAttribute)Attribute.GetCustomAttribute(member, descriptionAttributeType)).Description;
if (findMe.Equals(memberDescription))
{
Console.WriteLine("Found it!");
}
}
Note that all this reflection will be slow. Maybe you would be better off with an array of strings instead of an enumeration with descriptions.
Thank you so much for the positive feedback after reading through the posts I realized that my mistake was that answer was being set to an ENUM instead of an INT. I believe that this code format will give me the desired result:
if (request.Question4 != null)
{
var answersForQuestion4 = Enum.GetValues(typeof(IllinoisNonDisclosureConvictionFormOptions)).Cast<IllinoisNonDisclosureConvictionFormOptions>().ToList();
foreach (int answer in answersForQuestion4)
{
string descrip = Enum.GetName(typeof(IllinoisNonDisclosureConvictionFormOptions), answer);
if(descrip == request.Question4)
{
documentModel.Sections.Add(new Section(documentModel, new Paragraph(documentModel, descrip)));
}
}
}
This post helped a lot!
Get Enum from Description attribute

C# modifying a list in a function [duplicate]

This question already has answers here:
Directly modifying List<T> elements
(6 answers)
Closed 8 years ago.
I am writing a function which is passed in a list which is partially filled. I'd like to set some of the fields within the list inside this function. I thought that passing it as a reference would allow me to do this, however, I get the following error:
Error 1 Cannot modify the return value of 'System.Collections.Generic.List.this[int]' because it is not a variable
I am wondering what I might need to do to tell C# that I wish to have the option of modifying the contents of the list.
Here is a summarized version of my code:
public static void Determine_RTMM_Descriptor(ref List<Struct_Descriptor_Type> symbols, string Dwarf_Output_Filename)
{
...
lines = System.IO.File.ReadAllLines(Dwarf_Output_Filename);
//loop on symbol names
for (int idx = 0; idx < symbols.Count; idx++)
{
if(symbols[idx].size == 0)
symbols[idx].size = (int)new System.ComponentModel.Int32Converter().ConvertFromString(split_line[DwarfInterface.SIZE_INDEX]);
...
}
Thanks in advance for any help.
The underlying issue here is that you have a list of value types. When you use the indexer of the list to get an item from the list you are getting a copy of that type. The code symbols[idx] is the value of that item. It is not a variable representing that item, as the error message is telling you.
You're trying to mutate the size of the copy, which will have no effect on the item of the list. This is such a common mistake that the compiler even makes this an error.
If you really are sure that you want to have a mutable value type (hint: you aren't, and you shouldn't have one; you almost certainly just want to have a class here to avoid this problem entirely) then you would need to get the value of the item, mutate it, and then set the item again:
if(symbols[idx].size == 0)
{
var symbol = symbols[idx];
symbol.size = 42;
symbols[idx] = symbol;
}
Your return type on the function is "void" when you should set the return type to the list. That should allow you to change it and return it modified.

Can you have multiple enum values for the same integer? [duplicate]

This question already has answers here:
Non-unique enum values
(8 answers)
Closed 9 years ago.
In .NET can you have multiple enum values for the same integer?
eg.
public enum PersonGender
{
Unknown = 0,
Male = 1,
Female = 2,
Intersex = 3,
Indeterminate = 3,
NonStated = 9,
InadequatelyDescribed = 9
}
In C#, this is allowed, as per the C# Language Specication, version 4. Section 1.10 Enums doesn't explicitly mention the possibility but, later on in section 14 Enums, 14.3, we see:
Multiple enum members may share the same associated value. The example
enum Color {
Red,
Green,
Blue,
Max = Blue
}
shows an enum in which two enum members - Blue and Max - have the same associated value.
That works fine. There is absolutely nothing wrong with the code you posted. It compiles just fine and works in code, with the caveat that
PersonGender.NonStated == PersonGender.InadequatelyDescribed
I found this StackOverflow post related to this question. I think there is a very sensible discussion of how this works. Non-unique enum values
Now, I might also add that it is my opinion this would be an ambiguous (and therefore improper) use of an enum. It's important to write code that makes sense to someone else reading it, and in this case, I would be put off by this enum.
I would suggest that an enum would not be a right thing to use in your context instead you can use create a class and methods which can resolve your purpose. Something like this in your class:-
class A
{
static readonly ABCD= new Dictionary<int,string>
{
{ 1, "X" },
{ 2, "X" },
{ 3, "Y" }
{ 4, "Y" }
}
}

Categories