For some reason the HttpResponseMessageProperty which I'm using to return specific HTTP response codes to a client uses a HttpStatusCode enumeration. This enumeration does not include 422, which is not included in the enum. Is there any way to set an enumeration using an integer since that's what it is under the covers?
Yes, it's possible - internally an enum value is just an integer and you can "force" an enum value to have an invalid value and the CLR will continue on its merry way.
for example:
enum Foo {
Bar = 1,
Baz = 2
}
void Test() {
Foo foo; // as Foo is a value-type and no initial value is set, its value is zero.
Console.WriteLine( foo ); // will output "0" even though there is no enum member defined for that value
Foo foo2 = (Foo)200;
Console.WriteLine( foo2 ); // will output "200"
}
This is why, when working with enum values of unknown provenance, you should always handle the default case and handle appropriately:
public void DoSomethingWithEnum(Foo value) {
switch( value ) {
case Foo.Bar:
// do something
break;
case Foo.Baz:
// do something else
break;
default:
// I like to throw this exception in this circumstance:
throw new InvalidEnumArgumentException( "value", (int)value, typeof(Foo) );
}
}
You can cast any number into an enum, given the enum has the same base structure(usually it is int :
response.StatusCode = (HttpStatusCode)422;
Yes, you can have any value you want (as long as it is in range of enum's base type wich usally is int):
HttpStatusCode value = (HttpStatusCode)422;
Related
Why does this test pass? TestEnum doesn't contain and option with value "5". So this test should fail, but it doesn't.
private enum TestEnum
{
FirstOption = 2,
SecontOption = 3
}
[Test]
public void EnumTryParseIntValue()
{
TestEnum enumValue;
bool result = Enum.TryParse<TestEnum>(5.ToString(), out enumValue);
Assert.IsTrue(result);
}
Enum.TryParse Method (String, TEnum)
If value is a name that does not correspond to a named constant of
TEnum, the method returns false. If value is the string representation
of an integer that does not represent an underlying value of the TEnum
enumeration, the method returns an enumeration member whose underlying
value is value converted to an integral type. If this behavior is
undesirable, call the IsDefined method to ensure that a particular
string representation of an integer is actually a member of TEnum.
"Returns an enumeration member whose underlying value is value converted to an integral type"
If the value is not present you get back the integer. I don't consider getting back 5 to be an "enumeration member" but that is how it works. If you parse 2 you get FirstOption.
if (Enum.IsDefined(typeof(TestEnum), 5.ToString()))
{
result = Enum.TryParse<TestEnum>(5.ToString(), out enumValue);
Debug.WriteLine(result);
if (result)
{
Debug.WriteLine(enumValue.ToString());
}
}
Use Enum.IsDefined(Type enumType,Object value) - Returns an indication whether a constant with a specified value exists in a specified enumeration.
MSDN: Enum.IsDefined Method
I have the following enum declaration:
enum MyType
{
Boolean,
Int,
Double,
String
}
Then if I have a string abc = "anyvalue", how can I check whether the abc value is either bool, int, double or string corresponding to a myType enumerated value?
You can use Enum.TryParse method. This will return true if the value was successfully parsed into one of the enumeration values while also outputting the parsed enumeration value.
If you want to ignore case when performing the parsing use the overload that accepts a boolean parameter.
MyType type;
if (Enum.TryParse(abc, out type))
{
// can be parsed
switch (type)
{
case MyType.Boolean: break;
case MyType.Int: break;
case MyType.Double: break;
case MyType.String: break;
}
}
It's also possible to use Enum.IsDefined but this method always does a case-sensitive search so it is less flexible than Enum.TryParse and can only be used to know if the name is defined or not.
Use this:
MyType dummy;
if(bool isEnum = Enum.TryParse(mystring,out dummy))
{
// mystring is a valid enum
}
I'm bone new to generics in C#, and I'm attempting to create a method that will use generics. I tripped across the where keyword when attempting to create a local variable, so I'm sure that it will be part of the solution.
The reason for this is I have several different enum variables but the method would do the same to each (given a string that is one of the enum's defined values, toggle it on, using the enum like a bit field).
I have most of this together, the part I'm now stuck at is being able to tell the generic method it's ok to allow "|=" as I'm certain any type passed in will support the operator.
I would like to be able to maintain generality, if possible, so could either be an enum or a List and I would execute different code paths depending on the type.
Example of what I'm taking about
enum someType { value1 = 1<<0, value2 = 1<<1, value3 = 1<<2 }; // and so on
// some more enums
private T someMethod<T>(string myIdentifyers)
where T: new()
{
// suppose myIdentifiers is 1 more more of the valid enum options
// assume that the correct strings and enum combinations will be passed
T retval = new T();
while () {
// assume a loop with a method call that parses off one identifyer at a time
// if I have to convert the enum to an int first, so be it, but
// at this point I can't tell it that a cast to int exists
retval |= (T)System.Enum.Parse( typeof(T), oneIdentifyer, false );
}
return retval;
}
I would try something like this (pseudocode):
[Flags]
enum someType { value1 = 1<<0, value2 = 1<<1, value3 = 1<<2 }; // and so on
// some more enums
private T someMethod<T>(string myIdentifyers)
where T: struct, new()
{
// check if enum
if (typeof(T).BaseType != typeof(Enum)) // we should probably check for the flags attribute too
throw new Exception();
// suppose myIdentifiers is 1 more more of the valid enum options
// assume that the correct strings and enum combinations will be passed
int retval = 0;
while () {
// assume a loop with a method call that parses off one identifyer at a time
// if I have to convert the enum to an int first, so be it, but
// at this point I can't tell it that a cast to int exists
retval |= (int) (object) System.Enum.Parse( typeof(T), oneIdentifyer, false );
}
return (T) (object) retval;
}
It's not possible to express enum generic-constraints as of C# 4. Nor is it possible to express operator-constraints.
That said, I think you're looking for a method like this:
public static T AssembleFlagsEnum<T>(IEnumerable<string> names) where T : struct
{
return (T)(object)names.Aggregate(0,
(valSoFar, name) => valSoFar | Convert.ToInt32(Enum.Parse(typeof(T), name)));
}
Note that this doesn't validate that the type is a [Flags] enum. Nor will it work for enums which have underlying-types other than int.
In general, there's no good way to invoke operators on a generic type, although there are some kludges and workarounds that can help out in some circumstances.
See this similar question: Generic C# Code and the Plus Operator
In this case, since you know your enums cast to and from int, I think Bruno's method is the way to go.
Unfortunately it's not possible.
You can restrict with the struct constraint to say value type but obviously that includes more than integers. The only thing you could then do is early in the code to check on the actual type.
Supported constraint restrictions are described at http://msdn.microsoft.com/en-us/library/d5x73970.aspx
You can't do operator constraints - see Solution for overloaded operator constraint in .NET generics
I have two very similar but not identical C# objects. I am copying the values from one class to another.
Each class has some properties that expose an enumeration type. The inside of the enumerations are the same but the names are different e.g.
public enum EnumA
{
A,
B
}
public EnumA EnumAProperty
{
get{ return enumA;}
}
public enum EnumB
{
A,
B
}
public EnumB EnumBProperty
{
get{ return enumB;}
}
I want to assign the value returned from EnumBProperty to EnumAProperty is this possible?
You can do via casting but I would not recommend it as it is fragile — if any of the enum members are reordered or new items added the result may not be what you expect.
EnumAProperty = (EnumA) EnumBProperty;
Even worse with the casting is if you have items in your source enum with no equivalent in the destination — below there are more colours than shapes:
enum Color { Red = 0, Yellow = 1, Blue = 2 };
enum Shape ( Square = 0, Triangle = 1 };
Color color = Color.Red;
Shape shape = (Shape) color;
shape could end up with the value 2 even though this value is not defined.
Instead, I'd suggest you use a switch statement to map:
EnumAProperty = ConvertToA(EnumBProperty);
...
private static EnumA ConvertToA(EnumBProperty b)
{
switch (b)
{
case EnumB.Flannel: return EnumA.HandTowel;
case EnemB.Vest: return EnumA.UnderShirt;
...
default: throw new ArgumentOutOfRangeException("b");
}
}
Each enum member has a corresponding integer value.
By default, these values are assigned in ascending order, starting with 0.
If the order of the items in the enums (and thus their numeric values) are the same, you can just cast the numeric value to EnumB to get the EnumB member with the same value:
EnumBProperty = (EnumB)(int)EnumAProperty;
If not, you need to re-parse it:
EnumBProperty = (EnumB)Enum.Parse(typeof(EnumB), EnumAProperty.ToString());
As long as both enum's of different types you can'not assign it directly.
You can define integer offset for an items so you can assign values through the integer value
public enum EnumA
{
A = 0,
B = 1
}
public enum EnumB
{
A = 0,
B = 1
}
EnumBPropertry = (int)EnumAProperty
You could either cast it to an integer or convert it to a string and then do an Enum.Parse on it.
Try the following:
EnumAProperty = (EnumA)Enum.Parse(typeof(EnumA), EnumBProperty.ToString);
EnumBProperty = (EnumB)Enum.Parse(typeof(EnumB), EnumAProperty.ToString());
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Cast int to enum in C#
If I have the following code:
enum foo : int
{
option1 = 1,
option2,
...
}
private foo convertIntToFoo(int value)
{
// Convert int to respective Foo value or throw exception
}
What would the conversion code look like?
It's fine just to cast your int to Foo:
int i = 1;
Foo f = (Foo)i;
If you try to cast a value that's not defined it will still work. The only harm that may come from this is in how you use the value later on.
If you really want to make sure your value is defined in the enum, you can use Enum.IsDefined:
int i = 1;
if (Enum.IsDefined(typeof(Foo), i))
{
Foo f = (Foo)i;
}
else
{
// Throw exception, etc.
}
However, using IsDefined costs more than just casting. Which you use depends on your implemenation. You might consider restricting user input, or handling a default case when you use the enum.
Also note that you don't have to specify that your enum inherits from int; this is the default behavior.
I'm pretty sure you can do explicit casting here.
foo f = (foo)value;
So long as you say the enum inherits(?) from int, which you have.
enum foo : int
EDIT Yes it turns out that by default, an enums underlying type is int. You can however use any integral type except char.
You can also cast from a value that's not in the enum, producing an invalid enum. I suspect this works by just changing the type of the reference and not actually changing the value in memory.
enum (C# Reference)
Enumeration Types (C# Programming Guide)
Casting should be enough. If you're using C# 3.0 you can make a handy extension method to parse enum values:
public static TEnum ToEnum<TInput, TEnum>(this TInput value)
{
Type type = typeof(TEnum);
if (value == default(TInput))
{
throw new ArgumentException("Value is null or empty.", "value");
}
if (!type.IsEnum)
{
throw new ArgumentException("Enum expected.", "TEnum");
}
return (TEnum)Enum.Parse(type, value.ToString(), true);
}
if (Enum.IsDefined(typeof(foo), value))
{
return (Foo)Enum.Parse(typeof(foo), value);
}
Hope this helps
Edit
This answer got down voted as value in my example is a string, where as the question asked for an int. My applogies; the following should be a bit clearer :-)
Type fooType = typeof(foo);
if (Enum.IsDefined(fooType , value.ToString()))
{
return (Foo)Enum.Parse(fooType , value.ToString());
}
You don't need the inheritance. You can do:
(Foo)1
it will work ;)