Reputation: 2269
I am trying to cast an integer from a DataGridViewRow cell value which I have confirmed equals 0
AddedTask.Status = (TaskStatus) row.Cells["status"].Value;
Here is the code that creates the Task object and the TaskStatus Enum.
class Task
{
public string Description { get; set; }
public TimeSpan Duration
{
get
{
if (BeginDate == DateTime.MinValue) // BeginDate has not been set
return new TimeSpan(0, 0, 0);
else if (EndDate == DateTime.MinValue)
return DateTime.Now.Subtract(this.BeginDate);
else
return this.EndDate.Subtract(this.BeginDate);
}
}
public DateTime BeginDate { get; set; }
public DateTime EndDate { get; set; }
public TaskStatus Status { get; set; }
public Task()
{
this.Description = string.Empty;
this.BeginDate = new DateTime();
this.EndDate = new DateTime();
this.Status = TaskStatus.UNINVOICED;
}
}
public enum TaskStatus
{
UNINVOICED,
INVOICED,
PAID
}
Upvotes: 1
Views: 1941
Reputation: 43886
I tested around a little bit and observed that the cast succeeds if the original value is an Int32
but fails if it is (for example) an Int64
or a byte
.
My suggestes solution is to use Convert.ToInt32()
before the cast:
AddedTask.Status = (TaskStatus) Convert.ToInt32(row.Cells["status"].Value);
From learn.microsoft.com:
An enumeration is a set of named constants whose underlying type is any integral type. If no underlying type is explicitly declared, Int32 is used.
So your TaskStatus
enum is derived from Int32
and direct casts from any other integral types will fail.
Upvotes: 9
Reputation: 1086
As a side note. When you work with enum's you should work with the string of that enum, when persisting or exposing via services.
var value = TaskStatus.UNINVOICED;
var x = value.ToString();
var reversed = (TaskStatus)Enum.Parse(typeof(TaskStatus), x);
The reason you want to persist that is so you can modify your enum in the future. If on Day 1 your enum looks like this:
public enum TaskStatus
{
UNINVOICED,
INVOICED,
PAID
}
UNINVOICED may have an int value of 0, INVOICED may have a value of 1 and PAID may have a value of 2.
And then, if you need to update your enum to something like this:
public enum TaskStatus
{
NOTSET,
UNINVOICED,
INVOICED,
SOMEOTHERSTATUSBETWEENINVOICEDANDPAID,
PAID
}
Then all your persisted data gets redefined, if done by int. What was once UNINVOICED will now translate to NOTSET, and what was once PAID is now INVOICED.
And if you expose your through a service interface, depending on the Technology it will assign int values of the enum elements differently.
That is to say, that the enum exposed through Web Reference will NOT have that same int value as the enum exposed through Service Reference.
Always, persist your enum as string and always pass it around / convert it by enum or by string.
Upvotes: 1
Reputation: 13676
As a more generic approach you can create custom method that will convert all numeric types to any enumeration type you need :
static TEnum GetEnum<TEnum>(object obj)
where TEnum : struct, IConvertible
{
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("TEnum must be an enumerated type");
return (TEnum)(IConvertible)(Convert.ToInt32(obj));
}
Simple example of its usage :
enum Planet { Sun = 0, Moon = 1 }
enum Abc { Abc5 = 0, Abc30 = 1 }
private static void Main(string[] args)
{
var x = GetEnum<Planet>((long) 0);
var y = GetEnum<Abc>((double)1);
Console.Write(x);
Console.Write(", " + y);
}
Output: Sun, Abc30
Upvotes: 0
Reputation: 2269
This works but if this is the only way I am probably going to retire C#.
AddedTask.Status = (TaskStatus) Enum.Parse(typeof(TaskStatus), row.Cells["status"].Value.ToString());
Upvotes: 1