Generics - where T is a number? [duplicate] - c#

This question already has answers here:
Is there a constraint that restricts my generic method to numeric types?
(24 answers)
Closed 8 years ago.
I'm trying to figure a way to create a generic class for number types only, for doing some calculations.
Is there a common interface for all number types (int, double, float...) that I'm missing???
If not, what will be the best way to create such a class?
UPDATE:
The main thing I'm trying to achieve is checking who is the bigger between two variables of type T.

What version of .NET are you using? If you are using .NET 3.5, then I have a generic operators implementation in MiscUtil (free etc).
This has methods like T Add<T>(T x, T y), and other variants for arithmetic on different types (like DateTime + TimeSpan).
Additionally, this works for all the inbuilt, lifted and bespoke operators, and caches the delegate for performance.
Some additional background on why this is tricky is here.
You may also want to know that dynamic (4.0) sort-of solves this issue indirectly too - i.e.
dynamic x = ..., y = ...
dynamic result = x + y; // does what you expect
Re the comment about < / > - you don't actually need operators for this; you just need:
T x = ..., T y = ...
int c = Comparer<T>.Default.Compare(x,y);
if(c < 0) {
// x < y
} else if (c > 0) {
// x > y
}

There are interfaces for some of the operations on the number types, like the IComparable<T>, IConvertible and IEquatable<T> interfaces. You can specify that to get a specific functionality:
public class MaxFinder<T> where T : IComparable<T> {
public T FindMax(IEnumerable<T> items) {
T result = default(T);
bool first = true;
foreach (T item in items) {
if (first) {
result = item;
first = false;
} else {
if (item.CompareTo(result) > 0) {
result = item;
}
}
}
return result;
}
}
You can use delegates to expand a class with type specific operations:
public class Adder<T> {
public delegate T AddDelegate(T item1, T item2);
public T AddAll(IEnumerable<T> items, AddDelegate add) {
T result = default(T);
foreach (T item in items) {
result = add(result, item);
}
return result;
}
}
Usage:
Adder<int> adder = new Adder<int>();
int[] list = { 1, 2, 3 };
int sum = adder.AddAll(list, delegate(int x, int y) { return x + y; });
You can also store delegates in the class, and have different factory methods that sets up delegates for a specific data type. That way the type specific code is only in the factory methods.

Closest you get is struct I'm afraid. You'll have to do more extensive checks for number types in code.
public class MyClass<T> where T : struct
(...)

You cannot do this, since you'd have to use a single interface for arithmetic operations. There have been many requests on Connect to add an IArithmetic interface for this specific purpose, but so far they've all been rejected.
You can sort of work around this by defining a struct with no members, which implements a "Calculator" interface. We took this approach in an interpolation generic class in the Pluto Toolkit. For a detailed example, we have a "vector" calculator implementation here, which lets our generic interpolator work with vectors. There are similar ones for floats, doubles, quaternions, etc.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GenericPratice1
{
public delegate T Del<T>(T numone, T numtwo)where T:struct;
class Class1
{
public T Addition<T>(T numone, T numtwo) where T:struct
{
return ((dynamic)numone + (dynamic)numtwo);
}
public T Substraction<T>(T numone, T numtwo) where T : struct
{
return ((dynamic)numone - (dynamic)numtwo);
}
public T Division<T>(T numone, T numtwo) where T : struct
{
return ((dynamic)numone / (dynamic)numtwo);
}
public T Multiplication<T>(T numone, T numtwo) where T : struct
{
return ((dynamic)numone * (dynamic)numtwo);
}
public Del<T> GetMethodInt<T>(int ch) where T:struct
{
Console.WriteLine("Enter the NumberOne::");
T numone =(T) Convert.ChangeType((object)(Console.ReadLine()), typeof(T));
Console.WriteLine("Enter the NumberTwo::");
T numtwo = (T)Convert.ChangeType((object)(Console.ReadLine()), typeof(T));
T result = default(T);
Class1 c = this;
Del<T> deleg = null;
switch (ch)
{
case 1:
deleg = c.Addition<T>;
result = deleg.Invoke(numone, numtwo);
break;
case 2: deleg = c.Substraction<T>;
result = deleg.Invoke(numone, numtwo);
break;
case 3: deleg = c.Division<T>;
result = deleg.Invoke(numone, numtwo);
break;
case 4: deleg = c.Multiplication<T>;
result = deleg.Invoke(numone, numtwo);
break;
default:
Console.WriteLine("Invalid entry");
break;
}
Console.WriteLine("Result is:: " + result);
return deleg;
}
}
class Calculator
{
public static void Main(string[] args)
{
Class1 cs = new Class1();
Console.WriteLine("Enter the DataType choice:");
Console.WriteLine("1 : Int\n2 : Float");
int sel = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter the choice::");
Console.WriteLine("1 : Addition\n2 : Substraction\3 : Division\4 : Multiplication");
int ch = Convert.ToInt32(Console.ReadLine());
if (sel == 1)
{
cs.GetMethodInt<int>(ch);
}
else
{
cs.GetMethodInt<float>(ch);
}
}
}
}

In the Framework BCL (base class library), many numeric functions (such as the functions in System.Math) deal with this by having overloads for each numeric type.
The static Math class in the BCL contains static methods, which you can call without having to create an instance of the class. You could do the same in your class. For example, Math.Max has 11 overloads:
public static byte Max(byte val1, byte val2);
public static decimal Max(decimal val1, decimal val2);
public static double Max(double val1, double val2);
public static short Max(short val1, short val2);
public static int Max(int val1, int val2);
public static long Max(long val1, long val2);
public static sbyte Max(sbyte val1, sbyte val2);
public static float Max(float val1, float val2);
public static ushort Max(ushort val1, ushort val2);
public static uint Max(uint val1, uint val2);
public static ulong Max(ulong val1, ulong val2);

I don't believe you can define that using a generic type constraint. Your code could internally check your requirements, possibly using Double.Parse or Double.TryParse to determine if it is a number--or if VB.NET isn't out of the question then you could use the IsNumeric() function.
Edit: You can add a reference to Microsoft.VisualBasic.dll and call the IsNumeric() function from c#

You can not do it at compile time only.
But you could put more constraints to weed out most of 'bad types' on your numeric type like below
class yourclass <T>where T: IComparable, IFormattable, IConvertible, IComparabe<T>, IEquatable<T>, struct {...
In the end you would still have to check at runtime if your type is acceptable using object.GetType() method.
If only comparing, then IComparable<T> alone does the trick.

Related

Use same method to add 1 to a casted string that can be either float or int

Think this is a generic vs type specific problem.
I would like to add a unit to a string casted argument that can be an int or a float.
I tried the following, but there is problem at the time of the cast because the type is not known at compile time.
namespace ConsoleApp17
{
class Program
{
static int myInt = 1;
static float myFloat = 2f;
static void Main(string[] args)
{
string myFloatStr = "1.3";
string myIntStr = "2";
Add<float>(myFloatStr, SetNewFloatValue);
Add<int>(myIntStr, SetNewIntValue);
Console.ReadLine();
}
public static void Add<T>(string str, Action<T> action)
{
T valueToSet = (T)Math.Round(double.Parse(str) + 1, 0 , MidpointRounding.AwayFromZero); //problem here, cannot convert double to T
action(valueToSet);
}
private static void SetNewFloatValue(float floatArg) {
myFloat += floatArg;
}
private static void SetNewIntValue(int intArg)
{
myInt += intArg;
}
}
}
fiddle in case its helpful.
Is method overload for each of the arguments the only solution for this, or is there a more elegant solution so that the same funtionality can be dealt with in the one same method for both types float and int?
Meaning that:
Add<float>(myFloatStr, SetNewFloatValue);
Add<int>(myIntStr, SetNewIntValue);
could be done with the one same method.
"Generic Math" is what you want. This feature is a preview feature in .NET 6.0/C#10. It is described in detail here.
This allows method declarations such as this one:
public static TResult Sum<T, TResult>(IEnumerable<T> values)
where T : INumber<T>
where TResult : INumber<TResult>
{
TResult result = TResult.Zero;
foreach (var value in values)
{
result += TResult.Create(value);
}
return result;
}
The INumber interface is the magic of this concept. It is implemented on most numeric types now.
Previously, you had to implement that manually (by specifying your own INumber interface, with Add(), Subtract() etc. methods) or use the dynamic type to evaluate the correct types at runtime. The former was a lot of boilerplate to write for this, the later is slow.
If you are using older versions than .Net 6, you can use Convert.ChangeType for your case.
T valueToSet = (T)Convert.ChangeType(Math.Round(double.Parse(str) + 1, 0, MidpointRounding.AwayFromZero), typeof(T));

C# enum int not int [duplicate]

If I have the following enum:
public enum ReturnValue{
Success = 0,
FailReason1 = 1,
FailReason2 = 2
//Etc...
}
Can I avoid casting when I return, like this:
public static int main(string[] args){
return (int)ReturnValue.Success;
}
If not, why isn't an enum value treated as an int by default?
enums are supposed to be type safe. I think they didn't make them implicitly castable to discourage other uses. Although the framework allows you to assign a constant value to them, you should reconsider your intent. If you primarily use the enum for storing constant values, consider using a static class:
public static class ReturnValue
{
public const int Success = 0;
public const int FailReason1 = 1;
public const int FailReason2 = 2;
//Etc...
}
That lets you do this.
public static int main(string[] args){
return ReturnValue.Success;
}
EDIT
When you do want to provide values to an enum is when you want to combine them. See the below example:
[Flags] // indicates bitwise operations occur on this enum
public enum DaysOfWeek : byte // byte type to limit size
{
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64,
Weekend = Sunday | Saturday,
Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday
}
This enum can then be consumed by using bitwise math. See the below example for some applications.
public static class DaysOfWeekEvaluator
{
public static bool IsWeekends(DaysOfWeek days)
{
return (days & DaysOfWeek.Weekend) == DaysOfWeek.Weekend;
}
public static bool IsAllWeekdays(DaysOfWeek days)
{
return (days & DaysOfWeek.Weekdays) == DaysOfWeek.Weekdays;
}
public static bool HasWeekdays(DaysOfWeek days)
{
return ((int) (days & DaysOfWeek.Weekdays)) > 0;
}
public static bool HasWeekendDays(DaysOfWeek days)
{
return ((int) (days & DaysOfWeek.Weekend)) > 0;
}
}
There is no implicit cast because the enum does not have to use int as the underlying type. If your enum used a uint as the underlying type, for instance, there is no implicit cast from uint to int.
The c# enum is useless.
You can avoid casting from your type AND constrain the values that can be explicitly cast to your type by making a sealed class, and providing implicit/explicit conversion operators.
Provide an implicit operator for converting from your type to a generic int so you don't have to cast.
Provide an explicit operator for converting from an int to your type, which throws an error if the integer fails to meet the constraint, such as (int x) => (x >= 0 && x <= 2).
If using this technique, create a generic immutable base class such as ConstrainedNumber<T>, which has a constructor that accepts a T value and delegate for the constraint: delegate bool NumberConstraint<T>(T value). The constructor should run the value through the constraint delegate, and throw an exception if it fails to meet the constraint. The base class should also take care of the implicit conversion operation to T, and should handle equality by overloading object.Equals(object) and object.GetHashCode(), defining == and != operators for the type ConstrainedNumber<T>, and implementing IEquatable<T> and IEquatable<ConstrainedNumber<T>>. I also recommend defining an copy constructor for the base class, and all derived types. Cloning can then be implemented cleanly in the base class by retrieving the copy constructor via reflection, but this is entirely optional. You can figure out the ConstrainedNumber<T> implementation yourself, unless I've already posted it on stackoverflow somewhere.
You can provide named static readonly values in your derived ConstrainedNumber, so that you can access them just like an enum.
public sealed class ReturnValue: ConstrainedNumber<int>
{
public static readonly NumberConstraint<int> constraint = (int x) => (x >= 0 && x < 3);
public static readonly ReturnValue Success = new ReturnValue(0);
public static readonly ReturnValue FailReason1 = new ReturnValue(1);
public static readonly ReturnValue FailReason2 = new ReturnValue(2);
private ReturnValue( int value ): base( value, constraint ) {}
private ReturnValue( ReturnValue original ): base (original) {} //may be used to support IClonable implementation in base class
public static explicit operator ReturnValue( int value )
{
switch(value) //switching to return an existing instance is more efficient than creating a new one and re-checking the constraint when there is a limited number of allowed values; if the constraint was more generic, such as an even number, then you would instead return a new instance here, and make your constructors public.
{
case 0: return Success;
case 1: return FailReason1;
case 2: return FailReason2;
}
throw new ArgumentException( "Value fails to meet the constraint defined for " + typeof(ReturnValue).FullName + ".", "value" );
}
}
You could use this technique for any constraint. For example, a class called EvenNumber may have a constraint that returns true if the given number is even. In that case, you'd just make your constructors public, and simplify your static conversion operator to just return a new EvenNumber, instead of switching to return one of the limited existing instances.
It could be used like this:
EvenNumber x = (EvenNumber)2;
EvenNumber y = (EvenNumber)3; //throws exception "Value fails to meet the constraint defined for {namespace}.EvenNumber." A c# enum would stupidly allow such a cast, creating an invalid EvenNumber, breaking the object-oriented model
int z = x; //implicit conversion, no cast necessary;
Enums and ints are simply not implicitly castable as per the spec (except for the literal 0, which is allowed for comparison tests / assignments / etc). The explicit cast is all that is needed, though.
Strangely enough, this is not specific to the .NET Framework, but just to C#. As the other commenters have already pointed out, in C# this is basically a specification of the language. The same is not true in VB.NET.
Check out the MSDN reference page for Enums in VB.NET. Note that you can specify the data type of an enumeration at Enum declaration time.
That means, if you really don't want to litter your code with casts to (int), you could write your enumeration in VB.NET, declare it as an integer, then use that Enum from C#.
Remember how they told us computers would make our lives so much simpler? :)
No, you can't avoid casting; as to why there's no implicit conversion, I don't know, but there's not.
You can ascribe this behaviour to the basic intention behind creating Enumerations... to create a set of named constants that can only have specified (or default) values depending on the underlying type.
There are two separate issues to consider, as related to your question:
An Enum value cannot be treated as an int by default because then you would be able to provide any integer and there would be no compile time check to validate that the provided integer does in fact exist as a value in the Enumeration.
Casting becomes necessary since you are trying to convert from the governing type (of type YourCustomEnum which derives from the System.Enum class) to the underlying type, i.e., int or byte, etc.
Risking a Necromancer batch, I still like to post a possibility that didn't come up yet: To use a helper class (resp. struct) that converts implicitly into int and the enum type:
internal struct AutoCaster<T1, T2> {
private T1 Value1 { get; }
private T2 Value2 { get; }
public AutoCaster(T1 value1) {
Value1 = value1;
Value2 = (T2)(object)value1;
}
public AutoCaster(T2 value2) {
Value1 = (T1)(object)value2;
Value2 = value2;
}
public static implicit operator AutoCaster<T1, T2>(T2 input) {
return new AutoCaster<T1, T2>(input);
}
public static implicit operator AutoCaster<T1, T2>(T1 input) {
return new AutoCaster<T1, T2>(input);
}
public static implicit operator T1(AutoCaster<T1, T2> input) {
return input.Value1;
}
public static implicit operator T2(AutoCaster<T1, T2> input) {
return input.Value2;
}
}
As the Main needs a fix return type (int or void) it does not look that elegant in your example, but for other purposes it works just fine:
public static int Main(string[] args) {
return Main2(args);
}
private static AutoCaster<int, ReturnValue> Main2(string[] args) {
return ReturnValue.FailReason2;
}
How about using static Members of a Class?
//enum DocInfos { DocName, DocNumber, DocVersion};
public class DocInfos
{
public static int DocName = 0;
public static int DocNumer = 1;
public static int DocVersion = 2;
}
...
Doc = new string[DocInfos.DocVersion];
// Treffer
Doc[DocInfos.DocName] = TrimB(HTMLLines[lineCounter + 2])
...

Generic Structure - How to Constrain Type Parameter C# [duplicate]

This question already has answers here:
Is there a C# generic constraint for "real number" types? [duplicate]
(8 answers)
Closed 9 years ago.
I'm trying to make structure that represent four-dimensional vector.
I made something like this:
struct Vector4D<T>
{
public T v1;
public T v2;
public T v3;
public T v4;
//...
public static Vector4D<T> operator *(Vector4D<T> a, T b)
{
a.v1 *= b;
a.v2 *= b;
a.v3 *= b;
a.v4 *= b;
return a;
}
}
Well, this structure dosen't make sense if T isn't any numeric type like Int32, Int64, Double, Single, Decimal etc...
So, my question is how can I constrain T to be only one of following types, Int16, Int32, Int64, UInt16, UInt32, UInt64, Byte, SByte, Single, Double, Decimal?
I was trying do something like this
struct Vector4D<T> where T : Int16, Int32, Int64 // and so go on
{
//....
}
But it didn't work.
You do have to explicitly write a multiply method for each type.
However, you can simplify things a bit as this compilable code sample shows:
using System;
namespace Demo
{
internal class Program
{
static void Main()
{
var d = new Vector4D<double>{v1=1, v2=2, v3=3, v4=4};
Console.WriteLine(d*2); // Prints 2, 4, 6, 8
var i = new Vector4D<int>{v1=1, v2=2, v3=3, v4=4};
Console.WriteLine(i*2); // Prints 2, 4, 6, 8
// This will throw a "NotSupported" exception:
var s = new Vector4D<string>{v1="1", v2="2", v3="3", v4="4"};
Console.WriteLine(s*"");
}
}
partial struct Vector4D<T>
{
public T v1;
public T v2;
public T v3;
public T v4;
public static Vector4D<T> operator *(Vector4D<T> a, T b)
{
a.v1 = multiply(a.v1, b);
a.v2 = multiply(a.v2, b);
a.v3 = multiply(a.v3, b);
a.v4 = multiply(a.v4, b);
return a;
}
public override string ToString()
{
return string.Format("v1: {0}, v2: {1}, v3: {2}, v4: {3}", v1, v2, v3, v4);
}
private static Func<T, T, T> multiply;
}
// Partial just to keep this logic separate.
partial struct Vector4D<T>
{
static Vector4D() // Called only once for each T.
{
if (typeof(T) == typeof(int))
Vector4D<int>.multiply = (a, b) => a*b;
else if (typeof(T) == typeof(double))
Vector4D<double>.multiply = (a, b) => a*b;
else if (typeof(T) == typeof(float))
Vector4D<float>.multiply = (a, b) => a*b;
else
multiply = (a, b) =>
{
string message = string.Format("Vector4D<{0}> not supported.", typeof(T));
throw new NotSupportedException(message);
};
}
}
}
That way, you can put all the multiply (and presumably divide, add and subtract) logic into the second partial struct and keep it all separate from the main logic.
The second partial struct only contains a static type constructor which will be called once only (per assembly domain) for each type T which is used to create a struct.
You do have the overhead of querying the type, but it is only once per run of the program and I guess the overhead would be pretty low.
Also, you don't have to use a partial struct at all - you can just put the static type constructor with the rest of the struct implementation. I only separated it out as an example, because it is purely initialisation logic which you could consider separately from the rest of the struct's logic.
Important Note that if you use the Vector4D with a type for which you haven't defined a multiply operation, you'll get the NotSupportedException defined in static Vector4D(). This does at least tell you exactly what is wrong, along the lines of:
Unhandled Exception: System.NotSupportedException: Vector4D<System.String> not supported.
You cannot do this, not this way.
C# does not know anyhting about generic type T. Is it a number? Is it a string? Can you do math with it?
If you want to get this working, you have to use a generic calculator. You must build it yourself. For more info, take a look at: http://www.codeproject.com/Articles/8531/Using-generics-for-calculations
A simpler solution could be:
a.v1 = Convert.ChangeType(Convert.ToDecimal(a.v1) * Convert.ToDecimal(b), typeof(T));
EDIT
I created a few library functions on another location. You can use this to implement in your own code. Calculating with these numbers would be easy. Your Vector-class would be:
partial struct Vector4D<T>
where T: IComparable<T>, IEquatable<T>
{
public Number<T> v1;
public Number<T> v2;
public Number<T> v3;
public Number<T> v4;
public static Vector4D<T> operator *(Vector4D<T> a, T b)
{
a.v1 *= b;
a.v2 *= b;
a.v3 *= b;
a.v4 *= b;
return a;
}
}
See: https://codereview.stackexchange.com/questions/26022/improvement-requested-for-generic-calculator-and-generic-number

Has generic type's features/operator overloading improved in C# 5.0?

I know there are many question on SO like this
"Operator 'whatever' cannot be applied to operands of type 'T' (whatever may be ++, += or <= etc. etc. But bear with me, I wanna ask something different.
Let's say I have this code
public class GenericCls<T> where T : struct
{
public static T AddValues(params T[] values)
{
T sum = default(T);
if (values != null)
{
for (int i = 0; i < values.Length; i++)
{
sum += values[i];
}
}
return sum;
}
}
even though I've made my type struct, and value type I get the error
Operator '+=' cannot be applied to operands of type 'T' and 'T'
If I try to be subtle and apply the ValueType constraint, it says
Constraint cannot be special class 'System.ValueType'
If I try to turn the parameter in for loop to type T, and do this..
public class GenericCls<T> where T : struct, IComparable<T>, IEquatable<T>
{
public static T AddValues(params T[] values)
{
T sum = default(T);
if (values != null)
{
for (T i = default(T); i < values.Length; i++)
{
sum += values[i];
}
}
return sum;
}
}
I still get errors
Operator '<' cannot be applied to operands of type 'T' and 'int'
Operator '++' cannot be applied to operand of type 'T'
Cannot implicitly convert type 'T' to 'int'
No matter what, I can't get it to work. I am using VS2010 (C# 4.0, .NET 4.0). So I wanna know when C# 5.0 would be finally released with VS2012 (as far as I know they are still in beta stage right?) would it take care of these issues? Or are we again left with so many restriction on usage of Generics?
It is possible without language improvements, but you have to use some tricks and cannot apply it to existing numeric types, but have to create new ones. One of them is the curiously recurring pattern class C<T> : where T : C<T>. Another trick is to use static delegates for the operations. I define a numeric class like this (for the sake of simplicity I only define the addition):
public abstract class Numeric<T>
where T : Numeric<T>
{
public static Func<T, T, T> Add;
public static T operator +(Numeric<T> x, Numeric<T> y)
{
if (x == null) {
return (T)y;
}
if (y == null) {
return (T)x;
}
return Add((T)x, (T)y);
}
}
Note that we have to specify at least one type as Numeric<T> when overloading the operator (one type must always be the class that overloads the operator). Note also that we can cast Numeric<T> to T because of the generic constraint where T : Numeric<T>
Now we can declare a calculator like this. Since Numeric<T> overloads the + operator, we can use += here.
public class Calculator<T> where T : Numeric<T>
{
public static T AddValues(params T[] values)
{
T sum = default(T);
if (values != null) {
for (int i = 0; i < values.Length; i++) {
sum += values[i];
}
}
return sum;
}
}
Now lets define a concrete Numeric class. In the static constructor we define the static Add delegate. Since the operators are static, this delegate must be static as well because it is called from within the operator method, and since static members cannot be virtual, we must use this delegate-trick.
public class Complex : Numeric<Complex>
{
static Complex()
{
Add = (x, y) => new Complex(x.Re + y.Re, x.Im + y.Im);
}
public double Re { get; private set; }
public double Im { get; private set; }
public Complex(double re, double im)
{
Re = re;
Im = im;
}
public override string ToString()
{
return String.Format("({0}, {1})", Re, Im);
}
}
Now lets test this tricky construction
static class Test
{
public static void AddComplexNumbers()
{
// Using the calculator
var numbers = new Complex[] { new Complex(2, 7), new Complex(6, -2) };
var result = Calculator<Complex>.AddValues(numbers);
Console.WriteLine(result); // ==> (8, 5)
// Directly
var c1 = new Complex(2, 7);
var c2 = new Complex(6, -2);
result = c1 + c2;
Console.WriteLine(result); // ==> (8, 5)
}
}
No, it will not improve this issue. C#5 will offer async-await and a few minor features. But not an extended version of generics that works with method/operator overloading.
For comparisons you can use IComparer<T> and IComparable<T> as a workaround, but for arithmetic there is no good solution. There are a few techniques, but they either make the API ugly, or they're slow.
If I try to be subtle and apply the ValueType constraint, it says "Constraint cannot be special class System.ValueType"
The equivalent of this constraint is the struct keyword i.e. where T: struct. But constraining to value types does not gain you anything here. And why would it? There are value types that don't support arithmetic, and there are reference types that do. So being a value-type is orthogonal to what you need.
Unfortunately nothing changes with C# 5.0, which is currently in RC state. It focused mainly on async programming.

Can I avoid casting an enum value when I try to use or return it?

If I have the following enum:
public enum ReturnValue{
Success = 0,
FailReason1 = 1,
FailReason2 = 2
//Etc...
}
Can I avoid casting when I return, like this:
public static int main(string[] args){
return (int)ReturnValue.Success;
}
If not, why isn't an enum value treated as an int by default?
enums are supposed to be type safe. I think they didn't make them implicitly castable to discourage other uses. Although the framework allows you to assign a constant value to them, you should reconsider your intent. If you primarily use the enum for storing constant values, consider using a static class:
public static class ReturnValue
{
public const int Success = 0;
public const int FailReason1 = 1;
public const int FailReason2 = 2;
//Etc...
}
That lets you do this.
public static int main(string[] args){
return ReturnValue.Success;
}
EDIT
When you do want to provide values to an enum is when you want to combine them. See the below example:
[Flags] // indicates bitwise operations occur on this enum
public enum DaysOfWeek : byte // byte type to limit size
{
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64,
Weekend = Sunday | Saturday,
Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday
}
This enum can then be consumed by using bitwise math. See the below example for some applications.
public static class DaysOfWeekEvaluator
{
public static bool IsWeekends(DaysOfWeek days)
{
return (days & DaysOfWeek.Weekend) == DaysOfWeek.Weekend;
}
public static bool IsAllWeekdays(DaysOfWeek days)
{
return (days & DaysOfWeek.Weekdays) == DaysOfWeek.Weekdays;
}
public static bool HasWeekdays(DaysOfWeek days)
{
return ((int) (days & DaysOfWeek.Weekdays)) > 0;
}
public static bool HasWeekendDays(DaysOfWeek days)
{
return ((int) (days & DaysOfWeek.Weekend)) > 0;
}
}
There is no implicit cast because the enum does not have to use int as the underlying type. If your enum used a uint as the underlying type, for instance, there is no implicit cast from uint to int.
The c# enum is useless.
You can avoid casting from your type AND constrain the values that can be explicitly cast to your type by making a sealed class, and providing implicit/explicit conversion operators.
Provide an implicit operator for converting from your type to a generic int so you don't have to cast.
Provide an explicit operator for converting from an int to your type, which throws an error if the integer fails to meet the constraint, such as (int x) => (x >= 0 && x <= 2).
If using this technique, create a generic immutable base class such as ConstrainedNumber<T>, which has a constructor that accepts a T value and delegate for the constraint: delegate bool NumberConstraint<T>(T value). The constructor should run the value through the constraint delegate, and throw an exception if it fails to meet the constraint. The base class should also take care of the implicit conversion operation to T, and should handle equality by overloading object.Equals(object) and object.GetHashCode(), defining == and != operators for the type ConstrainedNumber<T>, and implementing IEquatable<T> and IEquatable<ConstrainedNumber<T>>. I also recommend defining an copy constructor for the base class, and all derived types. Cloning can then be implemented cleanly in the base class by retrieving the copy constructor via reflection, but this is entirely optional. You can figure out the ConstrainedNumber<T> implementation yourself, unless I've already posted it on stackoverflow somewhere.
You can provide named static readonly values in your derived ConstrainedNumber, so that you can access them just like an enum.
public sealed class ReturnValue: ConstrainedNumber<int>
{
public static readonly NumberConstraint<int> constraint = (int x) => (x >= 0 && x < 3);
public static readonly ReturnValue Success = new ReturnValue(0);
public static readonly ReturnValue FailReason1 = new ReturnValue(1);
public static readonly ReturnValue FailReason2 = new ReturnValue(2);
private ReturnValue( int value ): base( value, constraint ) {}
private ReturnValue( ReturnValue original ): base (original) {} //may be used to support IClonable implementation in base class
public static explicit operator ReturnValue( int value )
{
switch(value) //switching to return an existing instance is more efficient than creating a new one and re-checking the constraint when there is a limited number of allowed values; if the constraint was more generic, such as an even number, then you would instead return a new instance here, and make your constructors public.
{
case 0: return Success;
case 1: return FailReason1;
case 2: return FailReason2;
}
throw new ArgumentException( "Value fails to meet the constraint defined for " + typeof(ReturnValue).FullName + ".", "value" );
}
}
You could use this technique for any constraint. For example, a class called EvenNumber may have a constraint that returns true if the given number is even. In that case, you'd just make your constructors public, and simplify your static conversion operator to just return a new EvenNumber, instead of switching to return one of the limited existing instances.
It could be used like this:
EvenNumber x = (EvenNumber)2;
EvenNumber y = (EvenNumber)3; //throws exception "Value fails to meet the constraint defined for {namespace}.EvenNumber." A c# enum would stupidly allow such a cast, creating an invalid EvenNumber, breaking the object-oriented model
int z = x; //implicit conversion, no cast necessary;
Enums and ints are simply not implicitly castable as per the spec (except for the literal 0, which is allowed for comparison tests / assignments / etc). The explicit cast is all that is needed, though.
Strangely enough, this is not specific to the .NET Framework, but just to C#. As the other commenters have already pointed out, in C# this is basically a specification of the language. The same is not true in VB.NET.
Check out the MSDN reference page for Enums in VB.NET. Note that you can specify the data type of an enumeration at Enum declaration time.
That means, if you really don't want to litter your code with casts to (int), you could write your enumeration in VB.NET, declare it as an integer, then use that Enum from C#.
Remember how they told us computers would make our lives so much simpler? :)
No, you can't avoid casting; as to why there's no implicit conversion, I don't know, but there's not.
You can ascribe this behaviour to the basic intention behind creating Enumerations... to create a set of named constants that can only have specified (or default) values depending on the underlying type.
There are two separate issues to consider, as related to your question:
An Enum value cannot be treated as an int by default because then you would be able to provide any integer and there would be no compile time check to validate that the provided integer does in fact exist as a value in the Enumeration.
Casting becomes necessary since you are trying to convert from the governing type (of type YourCustomEnum which derives from the System.Enum class) to the underlying type, i.e., int or byte, etc.
Risking a Necromancer batch, I still like to post a possibility that didn't come up yet: To use a helper class (resp. struct) that converts implicitly into int and the enum type:
internal struct AutoCaster<T1, T2> {
private T1 Value1 { get; }
private T2 Value2 { get; }
public AutoCaster(T1 value1) {
Value1 = value1;
Value2 = (T2)(object)value1;
}
public AutoCaster(T2 value2) {
Value1 = (T1)(object)value2;
Value2 = value2;
}
public static implicit operator AutoCaster<T1, T2>(T2 input) {
return new AutoCaster<T1, T2>(input);
}
public static implicit operator AutoCaster<T1, T2>(T1 input) {
return new AutoCaster<T1, T2>(input);
}
public static implicit operator T1(AutoCaster<T1, T2> input) {
return input.Value1;
}
public static implicit operator T2(AutoCaster<T1, T2> input) {
return input.Value2;
}
}
As the Main needs a fix return type (int or void) it does not look that elegant in your example, but for other purposes it works just fine:
public static int Main(string[] args) {
return Main2(args);
}
private static AutoCaster<int, ReturnValue> Main2(string[] args) {
return ReturnValue.FailReason2;
}
How about using static Members of a Class?
//enum DocInfos { DocName, DocNumber, DocVersion};
public class DocInfos
{
public static int DocName = 0;
public static int DocNumer = 1;
public static int DocVersion = 2;
}
...
Doc = new string[DocInfos.DocVersion];
// Treffer
Doc[DocInfos.DocName] = TrimB(HTMLLines[lineCounter + 2])
...

Categories