In enum.cs there are two implementation of enum.IsDefined, the first one I always use is IsDefined(Type enumType, object value) works perfectly fine
But there is an other IsDefined, this one :
public static bool IsDefined<TEnum>(TEnum value) where TEnum : struct, Enum
{
RuntimeType enumType = (RuntimeType)typeof(TEnum);
ulong[] ulValues = Enum.InternalGetValues(enumType);
ulong ulValue = Enum.ToUInt64(value);
return Array.BinarySearch(ulValues, ulValue) >= 0;
}
source : Enum.cs
Is there any way this method could return false ?
It looks like a bug to me, this function should accept an Enum in parameter, not a TEnum. Or am I completely missing the point here ?
I would expect this function to work just like the overload, just being a synthaxic sugar
Thanks to Etienne de Martel
Yes it can return false, the idea is to cast before checking if the value is defined :
using System;
public enum E
{
V = 0
}
public class Program
{
public static void Main()
{
E e = (E)1;
Console.WriteLine(Enum.IsDefined(e));
}
}
The version that accepts object is OK, but it forces a "boxing" operation, i.e. it forces a heap allocation. In isolation, affordable, but: allocations add up. At the time, .NET didn't have generics, so: it was the best that could be done.
Generics serves as a mitigation against boxing (for value-types), so here it is used to avoid that overhead. It also makes calling it easier, since you don't need to specify the type at all in most cases (except perhaps when passing the literal zero). The compiler can infer the generics from the type of the argument.
Related
I have public functions like this:
public static T Get<T>(this Mango m, T defaultValue = default(T)) where T : class
{
//do something; return something;
}
public static T? Get<T>(this Mango m, T? defaultValue = default(T?)) where T : struct
{
//do something; return something;
}
Basically I want to individually handle reference types and nullable types. It compiles; until i call for value types. For reference types it compiles.
mango.Get<string>(); // compiles..
mango.Get(""); // compiles..
mango.Get<int>(); // The type 'int' must be a reference type in order to use it as
// parameter 'T' in the generic type or method Get<T>(Mango, T)
//also // The call is ambiguous between the following methods or properties:
// Get<int>(Mango, int) and Get<int>(Mango, int?)
What real ambiguity is here? When T is int, cant it call the struct overload appropriately? Also:
mango.Get<int>(0); // The type 'int' must be a reference type in order to use it as
// parameter 'T' in the generic type or method Get<T>(Mango, T)
Why is the compiler only detecting the reference type overload? I tried having two separate overloads:
public static T Get<T>(this Mango m) where T : class
{
return default(T);
}
public static T? Get<T>(this Mango m) where T : struct
{
return default(T);
}
public static T Get<T>(this Mango m, T def) where T : class
{
return default(T);
}
public static T? Get<T>(this Mango m, T? def) where T : struct
{
return default(T);
}
The problem persisted. And obviously, the first two methods dont compile here since overloading doesn't work merely on the basis of constraints.
I tried by removing the class constrained overload and keeping just the struct constrained one, like this:
public static T? Get<T>(this Mango m, T? defaultValue = default(T?)) where T : struct
{
//do something; return something;
}
mango.Get<int>(); // voila compiles!
mango.Get<int>(0); // no problem at all..
// but now I can't have mango.Get<string>() for instance :(
Am I only left with renaming the two functions? I feel its appropriate to have a unified name so that the caller just doesnt have to worry about the implementation detail, but just call Get for any type.
Update: Marc's solution doesnt work if I have to avoid the optional parameter.
mango.Get<int>(); // still wouldnt work!!
But there's more magic :(:(
public static bool IsIt<T>(this T? obj) where T : struct
{
return who knows;
}
public static bool IsIt<T>(this T obj) where T : class
{
return perhaps;
}
By all means I'm expecting the same compiler bug (according to me) to annoy me. But no it works this time.
Guid? g = null;
g.IsIt(); //just fine, and calls the struct constrained overload
"abcd".IsIt(); //just fine, and calls the class constrained overload
So if overload resolution comes before constraint checking as Marc says, shouldn't I get the same error this time too? But no. Why is it so?? What the hell is going on? :x
constraint checking is done after overload resolution, IIRC; the overload resolution seems to prefer the first version. You can force it to use the other, though:
mango.Get<int>((int?)0);
or even:
mango.Get((int?)0);
Personally, I'd probably just change the name to avoid the ambiguity.
Interestingly, the compiler will check the constraints specified within generic types that are used within a method signature, but not for constraints within the signature itself.
Thus, if a method accepted two parameters, one of type T where T : struct along with a Nullable<T>[], the compiler would not consider the method for any T that was not a struct. The method's specified struct constraint for T is not considered in evaluating overloads, but the fact that Nullable<T> constrains T to struct, is.
I really find the total inability to consider constraints in overload evaluation bizarre, given that one could specify a default null value for the Nullable<T>[] parameter, and pretend the parameter didn't exist. The vb.net compilers and C# compilers seem to differ, though, when it comes to what they regard as ambiguous and what they accept.
Let me try to answer myself.
As marc says, constraint checking is done after overload resolution, and between
public static T Get<T>(this Mango m, T defaultValue = default(T)) where T : class
{
//do something; return something;
}
and
public static T? Get<T>(this Mango m, T? defaultValue = default(T?)) where T : struct
{
//do something; return something;
}
overload resolution prefers the class version. But that's only when the compiler is given a choice between two similar overloads (without the optional parameter in which case both the overloads becomes the same, neglecting constraint). Now when the constraint is applied, the call fails for Get<int> since int is not class.
Things change a bit when default parameter is provided. If I call
mango.Get(0);
The compiler is able enough to call the right overload, but which overload now accepts int or T where T: struct? There is not one. In the given example, the second parameter is expected to be T? and not T. The compiler doesnt automatically resolve overloading by applying all the available casts for every argument type. It isn't a bug, but thats one less a feature, thats all. If I do this:
int? i = 0;
mango.Get(i);
it works, the right overload is called. This is what is happening in the second example too. It works because I'm providing the right parameter.
When I call:
Guid? g = null;
g.IsIt();
obj is known to be g and hence T equals Guid. But if I call
Guid g = Guid.NewGuid();
g.IsIt();
This doesn't work, since g is now Guid and not Guid? and compiler doesnt do the casting automatically, instead one have to tell the compiler explicitly.
I'm ok with the fact that the compiler doesn't do the casting automatically since that will be too much to calculate for every possible type, but what appears to be a deficiency in C# is the fact that constraint checking is not involved in overload resolution. That is even if I provide the type like mango.Get<int>() or mango.Get<int>(0) the overload resolution won't prefer the struct version and use default(int?) for argument defaultValue. Looks odd to me.
Surprisingly the following code fails the Assert:
int? wtf = 0;
Assert.IsType<Nullable<int>>(wtf);
So just out curiosity, how can you determine if a given instance is a Nullable<> object or not?
Well firstly, Nullable<T> is a struct, so there isn't an object as such. You can't call GetType(), as that will box the value (at which point you either get null and thus an exception, or a boxed non-nullable value and therefore not the type you want).
(Boxing is what's messing up your assertion here - I would assume that IsType accepts object.)
You can use type inference though to get the type of the variable as a type parameter:
public bool IsNullable<T>(T value)
{
return Nullable.GetUnderlyingType(typeof(T)) != null;
}
That's not a huge amount of use when you know the exact type at compile-time as in your example, but it's useful for generics. (There are alternative ways of implementing it, of course.)
What's your real life situation? I assume it's not an assertion like this, given that you know the answer to this one at compile time.
I like the #jon-skeet answer but it only works if you know the type you are testing against. In our world we are using reflection to open up objects and test values against regex expressions.
simplifying the extension to work for any type worked better for us.
public static bool IsNullable(this Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
generics are life's blood but sometimes... :)
int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(Nullable<>);
What namespace is Assert in?
The following returns true as you would expect:
int? wtf = 0;
if (typeof(Nullable<int>).IsInstanceOfType(wtf))
{
// Do things
}
Although its worth noting that typeof(Nullable<int>).IsInstanceOfType(42) also returns true - this is because this method accepts an object and so gets boxed as a Nullable<int>.
Here is what I came up with, as everything else seemed to fail - at least on Portable Class Library / DotNet Core with >= C# 6
Basically you extend generic Type Object and Nullable<T> and use the fact that the static extension method that matches the underlying type is going to be invoked and takes precedence over the generic T extension-method.
public static partial class ObjectExtension
{
public static bool IsNullable<T>(this T self)
{
return false;
}
}
and one for Nullable<T>
public static partial class NullableExtension
{
public static bool IsNullable<T>(this Nullable<T> self) where T : struct
{
return true;
}
}
Using Reflection and type.IsGeneric and type.GetGenericParameters() did not work on my current set of .NET Runtimes.
It works fo me, hope for you too.
public static bool IsNullable(this Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
Based on Vladimir answer:
public static class GenericExtensions
{
public static bool IsNullable<T>(this T item) =>
TypedReference.GetTargetType(__makeref(item)).FullName.Contains("System.Nullable");
}
Usage:
int? nullableInt = 42;
bool nIntIsNullable = nullableInt.IsNullable();
Duration: <2ms on average machine.
Remarks:
Important, this API is not CLS-compliant.
Contains("System.Nullable") can be more specific.
This works for me to check wether a type is Nullable or not..
type.Assembly.FullName.StartsWith("System") && type.Name.Contains("Nullable");
Only this way worked in my case using .net core 7
MyClass mclass = new MyClass();
PropertyInfo[] properties = mclass.GetType().GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
bool nullable = propertyInfo.GetMethod is null ? false : new NullabilityInfoContext().Create(propertyInfo.GetMethod.ReturnParameter).ReadState == NullabilityState.Nullable;
if (nullable)
{
//some script to do
}
}
WARNING: THIS CODE SUCKS, SEE ANTHONY'S COMMENTS
Which is faster?
1.
public bool IsValueType<T>(T obj){
return obj is ValueType;
}
2.
public bool IsValueType<T>(T obj){
return obj == null ? false : obj.GetType().IsValueType;
}
3.
public bool IsValueType<T>(T obj){
return default(T) != null;
}
4.Something else
You aren't really testing an object - you want to test the type. To call those, the caller must know the type, but... meh. Given a signature <T>(T obj) the only sane answer is:
public bool IsValueType<T>() {
return typeof(T).IsValueType;
}
or if we want to use an example object for type inference purposes:
public bool IsValueType<T>(T obj) {
return typeof(T).IsValueType;
}
this doesn't need boxing (GetType() is boxing), and doesn't have problems with Nullable<T>. A more interesting case is when you are passing object...
public bool IsValueType(object obj);
here, we already have massive problems with null, since that could be an empty Nullable<T> (a struct) or a class. But A reasonable attempt would be:
public bool IsValueType(object obj) {
return obj != null && obj.GetType().IsValueType;
}
but note that it is incorrect (and unfixable) for empty Nullable<T>s. Here it becomes pointless to worry about boxing as we are already boxed.
My first answer would be to write a simple test and find out for yourself.
My second answer (without any testing on my part, of course) would be option 1. It is the simplest check. The second method involves two separate checks while the third involves creating a default instance of a type.
You should also consider readability. The framework already gives you the ability to have the following in your code:
if(someObj is ValueType)
{
// Do some work
}
Why even bother creating a method that would simply turn the above statement into (assuming you made your method static and allowed the compiler to infer the generic type):
if(IsValueType(someObj))
{
// Do some work
}
Defining a struct actually defines two types: a value type, and a class type which derives from System.ValueType. If a request is made to create a variable, parameter, field, or array (collectively, 'storage location') of a type which derives from System.ValueType, the system will instead create a storage location which will store the object's fields rather than storing a reference to an object in which those fields appear. On the other hand, if a request is made to create an instance of a type deriving from System.ValueType, the system will create an object instance of a class which derives from System.ValueType.
This may be demonstrated by creating a struct which implements IValue:
interface IValue {int value {get; set;}};
struct ValueStruct : IValue
{
public int value {get; set;}};
}
with generic test routine and code to wrap it:
static void Test<T>(T it) where T:IValue
{
T duplicate = it;
it.value += 1;
duplicate.value += 10;
Console.WriteLine(it.value.ToString());
}
static void Test()
{
ValueStruct v1 = new ValueStruct();
v1.value = 9;
IValue v2 = v1;
Test<ValueStruct>(v1);
Test<ValueStruct>(v1);
Test<IValue>(v1);
Test<IValue>(v1);
Test<IValue>(v2);
Test<IValue>(v2);
}
Note that in every case, calling GetType on the parameter passed to Test would yield ValueStruct, which will report itself as a value type. Nonetheless, the passed-in item will only be a "real" value type on the first two calls. On the third and fourth calls, it will really be a class type, as demonstrated by the fact that a change to duplicate will affect it. And on the fifth and sixth calls, the change will be propagated back to v2, so the second call will "see" it.
static class Metadata<T>
{
static public readonly Type Type = typeof(T);
static public readonly bool IsValueType = Metadata<T>.Type.IsValueType;
}
//fast test if T is ValueType
if(Metadata<T>.IsValueType) //only read static readonly field!
{
//...
}
There are two rules:
1-All Classes are reference types such as Object and String, so it's supported by .NET Framework classes.
2-All structures are value types such as bool and char, even though it contain reference member, so it's supported by .NET Framework structures.
Simply right click on any type and Go To Definition if it's a Class so that means it a reference type else if it's a Struct so that means it's a value type :)
You can use
obj.GetType().IsValueType
This uses reflection but clear way instead of care of boxing unboxing.
Is it possible to constrain a generic method on specific types?
I want to write something like this:
public T GetValue<T>(string _attributeValue) where T : float, string
{
return default(T); // do some other stuff in reality
}
I'm mostly just trying to avoid having a giant switch statement inside the method or having to throw an exception if an invalid type is specified.
Edit: Ack. I knew string is not a value type. I started out with two numeric types earlier. Sorry.
You can't use generic constraints to express the limitations you are interested in. Generics are not meant to express variation based on disjoint types - they're meant to express variation that is unified over a hierarchy of types (or those implementing certain interfaces).
You have a few alternative choices, however. Which you choose depends on the exact nature of what you're trying to do.
Use differently named methods to express each operation. I tend to use this approach when each method is truly doing something different. You could argue that returning a different type of value from a method is essentially a different operation, and deserves its own unique name.
float GetFloat(string attrName) { }
string GetString(string attrName) { }
Provide a "default value" to allow the type to be inferred. In many designs where you ask for a value by name it useful to supply a default value. This can allow you to employ overloading to differentiate between which method to invoke (based on the type of the default value). Unfortunately, this approach is quite fragile - and breaks easily when passing literal values to overloads that accept numeric primitives (int vs. uint vs. long).
float GetValue(string attrName, float defaultValue) { ... }
string GetValue(string attrName, string defaultValue) { ... }
Use a generic method, but throw a runtime exception if the type isn't one of those you support. Personally I find this kind of ugly and in violation of the spirit of generics - generics should unify functionality over a hierarchy or a set of types implementing some interface. However, in some cases it makes sense to do so (if let's so one specific type cannot be supported, let's say). Another problem with this approach is that the signature of the generic method cannot be inferred from any parameters, so you would have to specify the type desired when calling it ... at which point it's not much better (from a syntax point of view) than having different method names.
T GetValue<T>( string attrName )
{
if( typeof(T) != typeof(string) ||
typeof(T) != typeof(float) )
throw new NotSupportedException();
return default(T);
}
// call it by specifying the type expected...
float f = GetValue<float>(attrName);
string s = GetValue<string>(attrName);
Use an out parameter instead of a return value. This approach works well, but it loses the concise syntax of being able to call a method and act on a return value, since you first have to declare a variable to populate.
void GetValue( string attrName, out float value )
void GetValue( string attrName, out string value )
// example of usage:
float f;
GetValue( attrName, out f );
string s;
GetValue( attrName, out s );
This is not possible to do with compile time support. You can do this check in the static constructor and throw an exception (in the case the T is defined on the type) or (in your case) in the method body itself, but in that case it would be a runtime validation.
No, you can not specify a range of types. If you want all primatives you can do (and i know string is not included)
where T: struct
No, it's not possible.
And string is a reference type, not a value type.
The closest you can get is constraining on all value types (minus Nullable types):
public T GetValue<T>(string _attributeValue) where T : struct
Depending on what you're actually doing inside the method, there may be various ways to achieve your goal (other than switch/case). Consider changing your example to be a little more meaningful...
One other option might also be to make your method private and provide public wrappers that are specific:
private T GetValue<T>(string _attributeValue) where T : struct
{
return default(T);
}
public float GetFloatValue(string _attributeValue)
{
return GetValue<float>(_attributeValue);
}
public int GetIntValue(string _attributeValue)
{
return GetValue<int>(_attributeValue);
}
That would allow you to constrain the public members of your class to the desired types but still use generic code internally so you don't have to repeat yourself.
I'd like to create a generic method for converting any System.Enum derived type to its corresponding integer value, without casting and preferably without parsing a string.
Eg, what I want is something like this:
// Trivial example, not actually what I'm doing.
class Converter
{
int ToInteger(System.Enum anEnum)
{
(int)anEnum;
}
}
But this doesn't appear to work. Resharper reports that you can not cast expression of type 'System.Enum' to type 'int'.
Now I've come up with this solution but I'd rather have something more efficient.
class Converter
{
int ToInteger(System.Enum anEnum)
{
return int.Parse(anEnum.ToString("d"));
}
}
Any suggestions?
If you don't want to cast,
Convert.ToInt32()
could do the trick.
The direct cast (via (int)enumValue) is not possible. Note that this would also be "dangerous" since an enum can have different underlying types (int, long, byte...).
More formally: System.Enum has no direct inheritance relationship with Int32 (though both are ValueTypes), so the explicit cast cannot be correct within the type system
I got it to work by casting to an object and then to an int:
public static class EnumExtensions
{
public static int ToInt(this Enum enumValue)
{
return (int)((object)enumValue);
}
}
This is ugly and probably not the best way. I'll keep messing with it, to see if I can come up with something better....
EDIT: Was just about to post that Convert.ToInt32(enumValue) works as well, and noticed that MartinStettner beat me to it.
public static class EnumExtensions
{
public static int ToInt(this Enum enumValue)
{
return Convert.ToInt32(enumValue);
}
}
Test:
int x = DayOfWeek.Friday.ToInt();
Console.WriteLine(x); // results in 5 which is int value of Friday
EDIT 2: In the comments, someone said that this only works in C# 3.0. I just tested this in VS2005 like this and it worked:
public static class Helpers
{
public static int ToInt(Enum enumValue)
{
return Convert.ToInt32(enumValue);
}
}
static void Main(string[] args)
{
Console.WriteLine(Helpers.ToInt(DayOfWeek.Friday));
}
If you need to convert any enum to its underlying type (not all enums are backed by int) then you can use:
return System.Convert.ChangeType(
enumValue,
Enum.GetUnderlyingType(enumValue.GetType()));
Why do you need to reinvent the wheel with a helper method? It's perfectly legal to cast an enum value to its underlying type.
It's less typing, and in my opinion more readable, to use...
int x = (int)DayOfWeek.Tuesday;
...rather than something like...
int y = Converter.ToInteger(DayOfWeek.Tuesday);
// or
int z = DayOfWeek.Tuesday.ToInteger();
From my answer here:
Given e as in:
Enum e = Question.Role;
Then these work:
int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);
The last two are plain ugly. The first one should be more readable, though the second one is much faster. Or may be an extension method is the best, best of both worlds.
public static int GetIntValue(this Enum e)
{
return e.GetValue<int>();
}
public static T GetValue<T>(this Enum e) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
return (T)(object)e;
}
Now you can call:
e.GetValue<int>(); //or
e.GetIntValue();
Casting from a System.Enum to an int works fine for me (it's also on the MSDN). Perhaps it's a Resharper bug.
Since Enums are restricted to byte, sbyte, short, ushort, int, uint, long and ulong, we can make some assumptions.
We can avoid exceptions during conversion by using the largest available container. Unfortunately, which container to use is not clear because ulong will blow up for negative numbers and long will blow up for numbers between long.MaxValue and ulong.MaxValue. We need to switch between these choices based on the underlying type.
Of course, you still need to decide what to do when the result doesn't fit inside an int. I think casting is okay, but there are still some gotchas:
for enums based on a type with a field space larger than int (long and ulong), it's possible some enums will evaluate to the same value.
casting a number larger than int.MaxValue will throw an exception if you are in a checked region.
Here's my suggestion, I'll leave it to the reader to decide where to expose this function; as a helper or an extension.
public int ToInt(Enum e)
{
unchecked
{
if (e.GetTypeCode() == TypeCode.UInt64)
return (int)Convert.ToUInt64(e);
else
return (int)Convert.ToInt64(e);
}
}
If you read the code for Convert.ToInt32, you can see that it casts the Enum to IConvertible, then calls ToInt32(null).
Don't forget that the Enum type itself has a bunch of static helper functions in it. If all you want to do is convert an instance of the enum to its corresponding integer type, then casting is probably the most efficient way.
I think ReSharper is complaining because Enum isn't an enumeration of any particular type, and enumerations themselves derive from a scalar valuetype, not Enum. If you need adaptable casting in a generic way, I would say this could suite you well (note that the enumeration type itself is also included in the generic:
public static EnumHelpers
{
public static T Convert<T, E>(E enumValue)
{
return (T)enumValue;
}
}
This could then be used like so:
public enum StopLight: int
{
Red = 1,
Yellow = 2,
Green = 3
}
// ...
int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red);
I can't say for sure off the top of my head, but the above code might even be supported by C#'s type inference, allowing the following:
int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);