Suppose I have enum, which underlying type is byte:
enum EmpType : byte
{
Manager = 1,
Worker = 2,
}
Can I cast some int literal to underlying type of this enum(byte in this case) ?
Something like this doesn't work (Error: "; expected"):
byte x = (Enum.GetUnderlyingType(typeof(EmpType)))15;
Can I cast to underlying type without explicitly writing (byte)15 ?
Thanks.
I think the following will work. But I'm not sure it will get you the desired behavior in all cases.
var x = Convert.ChangeType(15, Enum.GetUnderlyingType(typeof(EmpType)))
I'm not entirely sure what you're trying to do. Below is a related question about casting ints to enums and vice-versa, the same applies to byte in this case.
Is it possible to cast integer to enum?
If you want to detect the underlying type at run-time... it seems awkward and a lot of work. You could just do a case statement based upon the name of the underlying type. I'm not sure what good it would do you due to type safety concerns.
Related
What is the goal of explicitly casting an enum to it's declared type in, for example,
enum MyEnum : long
{
Zero,
One,
};
long one = (long)MyEnum.Zero; // <-- explicit conversion
Is there a logical explanation for this?
There are a few reasons but the main one that I use it for is when saving the field to a DB. The column in the DB has a data type that is int (in my case) and I use the conversion to allow me to save the enum value in the table.
The underlying type of enum (long in your case) specifies only how much storage is allocated for each enumerator. The type of enum itself is System.Enum so you need explicit cast.
That declaration tells compiler that you will use large values, but enum is still enum and it will not implicitly convert to any type. It's to be sure you know what you're doing, I think.
From C# Reference http://msdn.microsoft.com/pl-pl/library/sbbt4032.aspx
In the following example, the base-type option is used to declare an enum whose members are of type long. Notice that even though the underlying type of the enumeration is long, the enumeration members still must be explicitly converted to type long by using a cast.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
convert an enum to another type of enum
When casting between enums of different types, is it possibly to directly cast from one type to the other like so?
LicenseTypes type;
TypeOfLicense type2;
type2 = (TypeOfLicense)type;
Or is it necessary to cast the enum to an int first? The compiler doesn't complain, but I want to make sure I'm not going to get some kind of funky casting exception at runtime.
This may seem like an odd thing to do, but both enums are identical in structure and value. Only the type names differ in this case.
Although its a duplicate and I have flagged it as well. You can do simple casting, beucase the underlying type is int, you can do:
LicenseTypes type = (LicenseTypes)TypeOfLicense.value3;
Here type will hold value '0';
Suppose you have:
public enum LicenseTypes
{
value1,
value2,
}
public enum TypeOfLicense
{
value3,
value4,
value5
}
But if you try to Cast TypeOfLicence.value5 then the variable type will hold the int value 2
LicenseTypes type = (LicenseTypes)TypeOfLicense.value5;
You can also look at this link for creating extension methods for conversion between enums. (Its the accepted answer of the similar question)
No, but you can do this making a few assumptions ...
LicenseTypes type = LicenseTypes.Type1;
TypeOfLicense type2 = TypeOfLicense.Type2;
type2 = (TypeOfLicense)(int)type;
... and those assumptions are this. We must assume that both LicenseTypes and TypeOfLicense base int for their value. We must also assume that casting the underlying values to one another correlate from a business perspective (but that's really neither here nor there from a technical perspective).
Please note this works for other base types and it is possible to build a more complex conversion that would allow you to cast between different types with conversions.
No matter how you do it, it is merely an assignment of integer to another variable. Remember, enums are internally treated as integers and hence it will make no difference.
As far as I know, there are at least 3 ways to convert data types in .NET:
using System.ComponentModel.TypeConverter
var conv = System.ComponentModel.TypeDescriptor.GetConverter(typeof(int));
var i1 = (int)conv.ConvertFrom("123");
using System.Convert.ChangeType():
var i2 = (int) Convert.ChangeType("123", typeof (int));
using the Parse/TryParse methods of the destination type:
var i3 = int.Parse("123"); // or TryParse
Are there any guidelines or rules-of-thumb when to use which method to convert between the .NET base data types (especially from string to some other data type)?
I'm going to post here 6 years late, because I think this is a good question and I am not satisfied with the existing answers.
The static Parse/TryParse methods can be used only when you want to convert from string to the type that has those methods. (use TryParse when you expect that the conversion may fail).
The point of System.Convert is, as its documentation says, to convert from a base data type to another base data type. Note that with Convert you also have methods that take an Object and figure out by themselves how to convert it.
As to System.ComponentModel.TypeConverter, as the "typeconverter" stack overflow tag's documentation, they are used primarily to convert to and from string, when you want to provide a text representation of a class instance for use by designer serialization or for display in property grids
Convert
Convert class uses the IConvertible methods implemented in the target type.
Unfortunately, implementing IConvertible means writing lots of boilerplate code and Convert.ChangeType causes boxing if the target type is a struct.
TypeConverterAttribute
TypeDescriptor.GetConverter uses the TypeConverterAttribute and IMHO offers both a better API to convert a type and a more elegant way to make a type convertible. But it suffers the same performance issues with the Convert class, caused by the methods not being generic.
Parse/TryParse
Using T.Parse/T.TryParse methods is the de facto way of creating an object from a string since it doesn't involve unnecessary boxing. They also usually have overloads that provide greater control of how to parse the string.
TryParse methods allow you to handle cases where the string you want to parse is obtained from user input or another mean that doesn't guarantee a properly formatted string, without throwing exceptions.
So you should call the type's Parse/TryParse methods when you can and fallback to the other ways only when you don't know the target type in the compile time, i.e. when you only have a Type object that represents your target type.
You can also have look at my little library called ValueString that finds the most suitable parsing method of a type and uses it to parse the string.
According to my personal preference and coding standards I choose between the following:
Convert. I use this when I am absolutely sure that the values will be what I expect.
int i = Convert.ToInt32("123");
TryParse. I use this when I am handling user input. This also has the benefit to be able to use localized formatting when parsing.
int i = 0;
bool parsed = Int32.TryParse("123", out i);
There is also the possibility to use TryParseExact, where a certain pattern can be parsed. It can be useful in certain cases.
Just found out a case that TypeConvert.ConvertFrom(object) throws exception.
If you want to convert an Integer 0/1 to a Boolean. You will get exception using TypeConvert.ConvertFrom(1) or (0). In this case, Convert.ChangeType(1, System.Boolean) works.
As a general rule of thumb, you should be avoiding the Convert class altogether. There are reasons to use it (e.g, you do not know the source type), but if you already know your source type is a string then Parse (or, more correctly, TryParse) is always the right method to use.
As for type converters, they are more often than not used when a framework (such as WPF) uses reflection to determine the right sort of type converter.
You forgot another way of converting, that is the direct cast. Take this code for example
object i = 1;
int myInt = (int)i;
This is a bit of a contrived example, but I already know that i is an int, its just that its boxed into an object. In this case I do not need to convert i, I just need to directly cast it to the type which I know it already is.
I pretty much always use the int/double/etc.Parse() methods, when I'm certain it's a number. In any case of doubt, I us the .TryParse() methods, as an all-in-one solution including parsing and checking. I have this feeling that checking and parsing combined is slightly more performant than doing them separately.
TypeConverter is probably only useful when you don't really know the types at compile time.
Another late answer. I have an application where I was using some code that looks like this:
var finalValue = Convert.ChangeType(sourceValue, targetProperty.PropertyType);
sourceValue would be a string representation of what I wanted which normally would be a primitive under a wrapper class. This way would work with regular data types. Even with entire classes. However, one day I stupidly decided to change the datatype of a property that was a double to a nullable one double? guess what? boom!
invalid cast from string to nullable double
This is the perfect scenario where you should use the TypeConverter class as follows:
void Main()
{
var ss = new[] {"2.01", "3.99", ""};
var conv = TypeDescriptor.GetConverter(typeof(A).GetProperties().First().PropertyType);
Console.WriteLine(string.Join(",", ss.Select(s => conv.ConvertFrom(s))));
}
class A {
public double? b {get; set;}
}
//2.01,3.99,
I have a enumerator which map to a bunch of int
example
enum MyEnum {
Open = 1,
Closed = 2,
Exit = 4
}
I find though that when I want to assign this to an integer, I have to cast it first.
int myEnumNumber = **(int)** MyEnum.Open;
Is it possible to specify the type of an enum so that it is implicit that there is a integer assigned to any value within the enum? That way, I do not need to keep casting it to an int if I want to use it
thanks
No, this is on purpose - enums have an underlying data type, but they are not considered to be identical, because this possibly creates lots of error possibilities that this way are simple to catch.
For example you say so much about having to cast the num all the time - I can not remember when I did do a cast of an enum last time. And I do a LOT of C# programming.
enum MyEnum : int
{
Open = 1,
Closed = 2,
Exit = 4
}
This is also mentioned here.
However, this does not allow you to avoid casting, this allows it to be used with types other than Int32 (which is the default enum type).
In short, yes, you can specify a type but no, you still have to cast it.
There are a few good reasons and probably a lot of bad ones for converting enum values to ints, I'll assume you have a good reason ;).
If you are doing a lot of int casting an extension method might be helpful, here is a quicky extension method:
public static int EnumCast(this Enum theEnum)
{
return (int)((IConvertible)theEnum);
}
And an example of usage in a test:
[Test]
public void EnumCastTest()
{
Assert.That(MyEnum.Exit.EnumCast(), Is.EqualTo(4));
}
You can specify a different underlying type using:
enum : byte MyEnum { ... }
But this does not remove the need to cast to byte (if you really want to). Enums in C# allow you to normally just forget about the underlying type unless your applciation requires it.
Do you really need the underlying integer? It is possible to actually store a string representation of an enumeration value in a database and then recreate the enumeration value from the string at a later point, see this question.
MSDN gives a good tutorial on the do's and don't of enums.
Are C# enums typesafe?
If not what are the implications?
To give a slightly different answer... while the values are type-safe from the casting perspective, they are still unchecked once they have been cast - i.e.
enum Foo { A = 1, B = 2, C = 3 }
static void Main()
{
Foo foo = (Foo)500; // works fine
Console.WriteLine(foo); // also fine - shows 500
}
For this reason, you should take care to check the values - for example with a default in a switch that throws an exception.
You can also check the (for non-[Flags] values) via:
bool isValid = Enum.IsDefined(typeof(Foo), foo);
Yes they are.
The following is from http://www.csharp-station.com/Tutorials/Lesson17.aspx
Enums are strongly typed constants. They are essentially unique types that allow you to assign symbolic names to integral values. In the C# tradition, they are strongly typed, meaning that an enum of one type may not be implicitly assigned to an enum of another type even though the underlying value of their members are the same. Along the same lines, integral types and enums are not implicitly interchangable. All assignments between different enum types and integral types require an explicit cast.
For those suggesting to use Enum.IsDefined to do argument validation...don't! Per Brad Abrams (from the Framework Design Guidlines Update on Enum Design):
There are really two problems with Enum.IsDefined(). First it loads reflection and a bunch of cold type metadata making it a deceptively expensive call. Secondly, as the note alludes to there is a versioning issue here.
Yes.
C#: enum types:
-A type-safe enumeration of named values.
-Prevents programming errors
-User can control underlying type (defaults to int)
-Also can control underlying values
Technically no because you can represent an Enum as its base value (int, long, etc). However, if you ensure that you only use the enum by its provided names, you will receive compile time errors if you change the name of an enumerated value without updating its references. In this regard yes it is type safe.
I'm late to the party here, but I wanted to throw out a little something extra ... An update to the .NET Framework Design Guidelines from Krzysztof Cwalina. In addition to the excellent tip above on checking to ensure a valid value is passed to your Enums, this provides other guidance and advice for how to use them effectively, a bunch of gotchas (especially involved Flags enums), etc.
yes they r strongly-typed safed u cannot it does not do impilcit convertion of enum constant variables to integeral value u hv 2 expilcitly do dat
eg
enum days {
sun,
mon
}
int e = (int ) days.sun;
console.writeline(e);
C# enums are type safe meaning
You cannot implicitly convert from the underlying type to the actual enum
Also, you cannot assign a value of one enum to another enum, even though the underlying types of both the enums are same. An explicit cast is always required.
Enums make your code more readable and more maintainable.
I have come accross an excellent video tutorial on enums exaplaining their type safe nature. Have a look here and there.