Okay, for whatever reason I can't seem to figure this little problem out.
I have the following enum:
public enum EFeedType
{
TypeOne = 1,
TypeTwo = 2
}
Now, I am going to be getting the numeric value from a database. Well, I need to cast the int value from the DB to the enum type:
EDIT:
The database type is integer, so I do not need to cast from string.
END EDIT
EFeedType feedType = (EFeedType) feedId;
However, when I do this, and pass in value of 2 I get the following error:
Instance validation error: '2' is not a valid value for [Namespace Goes Here].EFeedType.
Any thoughts on what I might be doing wrong or missing?
EDIT
Here is the code I am using:
//GetFeed will return an int value which is pulled from the database
int feedId = new FeedEngine().GetFeed("FeedName");
//Convert the ID to the Enum
EFeedType feedType = (EFeedType) feedId;
//Set the User Control FeedType Enum to the enum
FeedControl.FeedType = feedType;
//Show the user control
FeedControl.Visible = true;
EDIT - More Info
Okay, after seeing JSkeet's response, I see that If my feedId = 1 then it will set the enum value to TypeTwo instead of TypeOne like it should. Maybe I need a Default = 0 value in my enum for this to work? But there has to be a better way, because what if my values are not in sequence.
Your error won't be coming from the line you showed it on. I strongly suspect it's coming from this line:
FeedControl.FeedType = feedType;
My guess is that that property is doing some validation - and that it doesn't know about the relevant value.
EDIT: Note that if you do want to find out if a value is valid, use Enum.IsDefined. Enum.Parse will not throw an exception for an incorrect numeric value, so long as it's in the right range.
Have you really posted the exact code of the enum? Because if it doesn't explicitly specify the "= 1" and "= 2" it will autoincrement from 0, and that will be your problem.
If you could demonstrate all of this with a short but complete program it would really help. There's no need to go to the database, and no need to do anything with a user control.
I just tried the following and it worked perfectly. You might want to break your code out into a little test project to see what's going on.
// enum definition
public enum EFeedType {
TypeOne = 1,
TypeTwo = 2,
}
// usage
private void TestEnum() {
Int32 feedId = 2;
EFeedType stuff = (EFeedType)Enum.Parse(typeof(EFeedType), feedId.ToString());
Response.Write(stuff.ToString());
}
Related
I am developing my first registration form in ASP.NET MVC and I am presenting the following error
Argument 2: cannot convert from 'out string' to 'out int'
var ticketPriorityInput = "ALTO";
if (int.TryParse(Request.Form["ticketPriorityInput"], out ticketPriorityInput) == false)
{
}
ticketPriorityInput is of type string
I do this because I need to validate that when the ticketPriorityInput field is saved to save it by default with the string "ALTO", you can tell me how it is the best way to do it or how I can fix it
I explain better a form but depending on the session variables certain fields are loaded, ticketPriorityInput has to go in both one and the other, the difference is that in which I need also goes ticketPriorityInput but it is not being entered I need it to be stored by default value "ALTO"
var ticketPriorityInput is explicity a string because you initialized it to a string.
try:
var ticketPriorityInput = 0;
if (int.TryParse(Request.Form["ticketPriorityInput"], out ticketPriorityInput) == false)
{
}
if you dont want to change ticketPriorityInput, create a different variable that is an int for ticketPriorityInput to save to.
If I understand you correctly, you want to convert the value of Request.Form["ticketPriorityInput"] to int and save the result in ticketPriorityInput if successful, and if not successful, you want ticketPriorityInput to contain the string "ALTO".
So you would still have to use two variables; there's no way getting around the requirement to pass an int to the int.TryParse() method. But you can make ticketPriorityInput into type dynamic and use this:
dynamic ticketPriorityInput = "ALTO";
if (int.TryParse(Request.Form["ticketPriorityInput"], out int tInt))
{
ticketPriorityInput = tInt;
}
Now, if the conversion is successful ticketPriorityInput will contain the converted integer, otherwise the value "ALTO".
After reading the comments of all users and none understood what my question was saying despite being updated with a clearer explanation I found the solution to my problem in this way
var ticketPriorityInput = Request.Form["ticketPriorityInput"];
var ticketPriorityInputByDefault = "ALTO";
if (String.IsNullOrEmpty(ticketPriorityInput)){
ticketPriorityInput = ticketPriorityInputByDefault;
}
So i have this old code that uses Firebird, i took the code from there since it worked perfectly, but here it doesnt. and throws me a InvalidCastException.
So wat am i trying
animal.FeedScheduleType = (BcFeedScheduleType)drAnimal["feedschedule_type"];
So i try to pull something out my datatable and place it in animal.FeedScheduleType. Now my cast points a a public enum
public enum BcFeedScheduleType
{
Default = 0,
FromList = 1,
Group = 2
}
and animal.FeedScheduleType is
private BcFeedScheduleType _feedScheduleType;
public BcFeedScheduleType FeedScheduleType
{
get { return _feedScheduleType; }
set { _feedScheduleType = value; }
}
But whenever it hits this it throws me the InvalidCastException error and i dont know why, i searched here and google but was unable to find anything about casts like this.
Edit: the Type inside the database is a integer
Try this:
animal.FeedScheduleType = (BcFeedScheduleType)Convert.ToInt32(drAnimal["feedschedule_type"]);
Here is a fiddle.
Have you tried casting to an int first?
animal.FeedScheduleType = (BcFeedScheduleType)(int)drAnimal["feedschedule_type"];
My guess is that your drAnimal is returning a string and not an int. If this is the case, then
animal.FeedScheduleType = (BcFeedScheduleType)Int.Parse(drAnimal["feedschedule_type"]);
If you are not sure what type drAnimal is, you can do something like:
var feedschedule_type = drAnimal["feedschedule_type"];
Console.WriteLine("feedschedule_type is {0}", typeof(feedschedule_type));
Basically, you need to get it into an int and then use the standard cast as you've done in your question.
Finally, make sure the feed schedule type has a valid value. I.e., make sure its value is either 0, 1 or 2.
I actually just ran into this recently when using SqlParameter.
My guess is that drAnimal["feedschedule_type"] is being stored as a SqlDbType.Int or object. In order to cast my parameter, I had to do something similar to the following:
(int)(SqlDbType.Int)(drAnimal["feedschedule_type"]);
You may have to use a similar chain to get the actual int value and coerce it into your Enum.
I have a scenario where I'm using a Dictionary to hold a list of transaction types that a certain system accepts. The key in the Dictionary is an enum field, the value is an int.
At some point in the system, we're going to want to do something like this:
sqlCommand.Parameters.AddWithValue("#param", LookupDictionary[argument.enumField]);
When we look up the field in the dictionary, we're going to get the correct integer value to feed to the database. I've thought about actually using the enum int value for this, but that's not exactly right. We're interacting with a system where we need to feed a magic number in to represent the kind of update we're doing.
The code above works just fine. I have an initializer method that adds the known types:
LookupDictionary = new Dictionary<mynamespace.myproject.myclass.enumType, int>();
LookupDictionary.Add(enumType.entry1, 4);
LookupDictionary.Add(enumType.entry2, 5);
LookupDictionary.Add(enumType.entry3, 6);
This code also works fine.
But up above, before I actually get in to using the LookupDictionary, I validate that the request being made is actually set to an enum value we support. That's LookupDictionary's main reason to be, it holds the valid ones (there are valid enum entries that this method doesn't work with).
This is the code that doesn't work: the system fails to recognize that the enums match. In the debugger, I can see that the entries list in LookupDictionary does show that it has the value for entry2 - it just calls it like that, entry2. The incoming enumField on the other hand has the full namespace; mynamespace.myproject.myclass.enumType.entry2 - I imagine this is why it doesn't see them as being the same.
if (!LookupDictionary.ContainsKey(argument.enumField))
{
throw new InvalidOperationException("argument.enumField not valid in blahMethod.");
}
Did I mention that this is being passed across a WCF service? But I'm not using an auto-generated proxy ... both projects on both sides of the wire share the types as a project reference, and I build up my channel client in code.
Any ideas? Am I doing it wrong? Do Dictionaries with Enums as keys not work well? Is it a WCF thing?
Note: thanks for the suggestions regarding setting the enums up to contain the magic int. I wanted to set those in a configuration, however, as its possible that the "magic numbers" 4 5 and 6 might change down the road. So if I code them in to the enum as suggested:
public enum MyEnum
{
MyValue1 = 4,
MyValue2 = 5,
MyValue3 = 6
}
I lose the ability to write a method that sets up the magic numbers in the future at run time; instead it would require a code change.
Instead of using the enum as the key, use the integer representation of the enum.
For instance:
LookupDictionary = new Dictionary<int, int>();
LookupDictionary.Add((int)enumType.entry1, 4);
LookupDictionary.Add((int)enumType.entry2, 5);
LookupDictionary.Add((int)enumType.entry3, 6);
That way, you can use the same 'ContainsKey' method of the dictionary. I'm not sure this is much better performance than a List<int>
You shouldn't need a lookup table here at all:
public enum MyEnum
{
MyValue1 = 4,
MyValue2 = 5,
MyValue3 = 6
}
// Sample usage
MyEnum firstEnum = MyEnum.MyValue1;
int intVal = (int)firstEnum; // results in 4
// Enum Validation
bool valid = Enum.IsDefined(typeof(MyEnum), intVal); // results in true
Can you considered typing your enumeration explicitly as int (or whatever the underlying type is) and then setting the value of each of your enumerations to the database value? You've already tightly coupled the enumeration to the database, so either the relationship will be dictated in C# (current hard-coding) or by SQL (perhaps a proc that returns the ID as well as a string that can be parsed into an enumeration.)
Using the assumption that your enumeration is an int...
enum enumType {
entry1 = 4,
entry2 = 5,
entry3 = 6
}
When adding your parameter you would then just cast as the enum's underlying type.
sqlCommand.Parameters.AddWithValue("#param", (int)argument.enumField);
You can explicitly set the values of the enum using the syntax
enum ArgumentTypes {
Arg1 = 1;
Arg2 = 3;
Arg3 = 5;
}
You don't need to keep each value sequential in the enum for this syntax to work.
To validate that only parameters that are valid for the method are ever used, try this sample code. Note I suggest using an ArgumentException over an InvalidOperationException in this context.
public void DoDbWork(ArgumentTypes argType, object otherParameter)
{
if (argType == ArgumentTypes.Arg3) {
throw new ArgumentException("Argument of value " + argType + " is not valid in this context", "argType");
}
// Handle db transaction here
}
To add the int value as the parameter:
cmd.Parameters.AddWithValue("#paramName", (int)argType);
considering the following enum:
public enum LeadStatus
{
Cold = 1,
Warm = 2,
Hot = 3,
Quote = 5,
Convert = 6
}
How can I convert the integer value back to string when I pull the value from a database. I've tried:
DomainModel.LeadStatus status = (DomainModel.LeadStatus)Model.Status;
but all I seem to get is "status = 0"
What you are looking for is Enum.Parse.
"Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object."
Here is the MSDN page: http://msdn.microsoft.com/en-us/library/essfb559.aspx
Example:
enum Colour
{
Red,
Green,
Blue
}
// ...
Colour c = (Colour) Enum.Parse(typeof(Colour), "Red", true);
Courtesy of http://blogs.msdn.com/tims/archive/2004/04/02/106310.aspx
Between Enum.Parse and Enum.ToString, you should be able to do everything you need.
Given "Model.Status" is the integer from the database, it can be restored to the Enum string value with:
string status = Enum.GetName(typeof(DomainModel.LeadStatus), Model.Status);
Just use ToString() on the enum object
An enumeration in C# is used to provide names for some known values but ANY integer value is permissible in that enumeration, whether it has a named equivalent or not.
In your example, you have not named a zero value, but your status variable initialises to zero. I suspect that it has not changed from this initial value at the point you read it. Therefore, it's string representation is also 0 and you will parse out zero when you parse it.
say I have the following declarations:
public enum Complexity { Low = 0, Normal = 1, Medium = 2, High = 3 }
public enum Priority { Normal = 1, Medium = 2, High = 3, Urgent = 4 }
and I want to code it so that I could get the enum value (not the index, like I earlier mentioned):
//should store the value of the Complexity enum member Normal, which is 1
int complexityValueToStore = EnumHelper.GetEnumMemberValue(Complexity.Normal);
//should store the value 4
int priorityValueToStore = EnumHelper.GetEnumMemberValue(Priority.Urgent);
How should this reusable function look like?
tia!
-ren
Revised answer (after question clarification)
No, there's nothing cleaner than a cast. It's more informative than a method call, cheaper, shorter etc. It's about as low impact as you could possibly hope for.
Note that if you wanted to write a generic method to do the conversion, you'd have to specify what to convert it to as well: the enum could be based on byte or long for example. By putting in the cast, you explicitly say what you want to convert it to, and it just does it.
Original answer
What do you mean by "index" exactly? Do you mean the numeric value? Just cast to int. If you mean "position within enum" you'd have to make sure the values are in numeric order (as that's what Enum.GetValues gives - not the declaration order), and then do:
public static int GetEnumMemberIndex<T>(T element)
where T : struct
{
T[] values = (T[]) Enum.GetValues(typeof(T));
return Array.IndexOf(values, element);
}
You can find the integer value of an enum by casting:
int complexityValueToStore = (int)Complexity.Normal;
The most generic way I know of is to read the value__ field using reflection.
This approach makes no assumptions about the enum's underlying type so it will work on enums that aren't based on Int32.
public static object GetValue(Enum e)
{
return e.GetType().GetField("value__").GetValue(e);
}
Debug.Assert(Equals(GetValue(DayOfWeek.Wednesday), 3)); //Int32
Debug.Assert(Equals(GetValue(AceFlags.InheritOnly), (byte) 8)); //Byte
Debug.Assert(Equals(GetValue(IOControlCode.ReceiveAll), 2550136833L)); //Int64
Note: I have only tested this with the Microsoft C# compiler. It's a shame there doesn't appear to be a built in way of doing this.
I realize this isn't what you asked, but it's something you might appreciate.
I discovered that you can find the integer value of an enum without a cast, if you know what the enum's minimum value is:
public enum Complexity { Low = 0, Normal = 1, Medium = 2, High = 3 }
int valueOfHigh = Complexity.High - Complexity.Low;
This wouldn't work with Priority, unless you added some minimal value of 0, or added 1 back:
public enum Priority { Normal = 1, Medium = 2, High = 3, Urgent = 4 }
int valueOfUrgent = Priority.Urgent - Priority.Normal + 1;
I find this technique much more aesthetically appealing than casting to int.
I'm not sure off the top of my head what happens if you have an enum based on byte or long -- I suspect that you'd get byte or long difference values.
If you want the value, you can just cast the enum to int. That would set complexityValueToStore == 1 and priorityValueToStore == 4.
If you want to get the index (ie: Priority.Urgent == 3), you could use Enum.GetValues, then just find the index of your current enum in that list. However, the ordering of the enum in the list returned may not be the same as in your code.
However, the second option kind of defeats the purpose of Enum in the first place - you're trying to have discrete values instead of lists and indices. I'd rethink your needs if that is what you want.
This is the most simple way to solve your problem:
public static void GetEnumMemberValue<T>(T enumItem) where T : struct
{
return (int) Enum.Parse(typeof(T), enumItem.ToString());
}
It works for me.