Generic number validation [duplicate] - c#

This question already has answers here:
Is there a constraint that restricts my generic method to numeric types?
(24 answers)
Closed 9 years ago.
I've got a method like this:
public static bool IsPercentage<T>(T value) where T : IComparable
{
return value.CompareTo(0) >= 0 && value.CompareTo(1) <= 0;
}
I would like to use this to validate if any number falls in the range 0 <= N <= 1. However this only works with integers since CompareTo only operates on equal types. Is there a different way to do this?

well you could use Convert.ToDecimal, then you don't need to be generic:
public static bool IsPercentage(Object value)
{
decimal val = 0;
try
{
val = Convert.ToDecimal(value);
}
catch
{
return false;
}
return val >= 0m && val <= 1m;
}

You can use Expression Tree to do this. Consider helper, static class
static class NumericHelper<T>
{
public static T Zero { get; private set; }
public static T One { get; private set; }
static NumericHelper()
{
Zero = default(T);
One = Expression.Lambda<Func<T>>(
Expression.Convert(
Expression.Constant(1),
typeof(T)
)
).Compile()();
}
}
It generates (T)1 cast at runtime and assign result to One property. Because static constructor is fired only once code necessary to generate properly typed 1 value will be executed only once for every T.
public static bool IsPercentage<T>(T value) where T : IComparable
{
return value.CompareTo(NumericHelper<T>.Zero) >= 0 && value.CompareTo(NumericHelper<T>.One) <= 0;
}
Ofc, it will fail if you try to call it with type T which don't support (T)1 conversion.

Related

How to convert the integer associated with a value of an enum to string [duplicate]

I have the following enum:
public enum Urgency {
VeryHigh = 1,
High = 2,
Routine = 4
}
I can fetch an enum "value" as string like this:
((int)Urgency.Routine).ToString() // returns "4"
Note: This is different from:
Urgency.Routine.ToString() // returns "Routine"
(int)Urgency.Routine // returns 4
Is there a way I can create an extension class, or a static utliity class, that would provide some syntactical sugar? :)
You should just be able to use the overloads of Enums ToString method to give it a format string, this will print out the value of the enum as a string.
public static class Program
{
static void Main(string[] args)
{
var val = Urgency.High;
Console.WriteLine(val.ToString("D"));
}
}
public enum Urgency
{
VeryHigh = 1,
High = 2,
Low = 4
}
In order to achieve more "human readable" descriptions for enums (e.g. "Very High" rather than "VeryHigh" in your example) I have decorated enum values with attribute as follows:
public enum MeasurementType
{
Each,
[DisplayText("Lineal Metres")]
LinealMetre,
[DisplayText("Square Metres")]
SquareMetre,
[DisplayText("Cubic Metres")]
CubicMetre,
[DisplayText("Per 1000")]
Per1000,
Other
}
public class DisplayText : Attribute
{
public DisplayText(string Text)
{
this.text = Text;
}
private string text;
public string Text
{
get { return text; }
set { text = value; }
}
}
Then, used an extension method like this:
public static string ToDescription(this Enum en)
{
Type type = en.GetType();
MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(
typeof(DisplayText),
false);
if (attrs != null && attrs.Length > 0)
return ((DisplayText)attrs[0]).Text;
}
return en.ToString();
}
You can then just call myEnum.ToDescription() in order to display your enum as more readable text.
If you want to just deal with this enum, use Mark Byer's solution.
For a more general solution:
public static string NumberString(this Enum enVal)
{
return Convert.ToDecimal(enVal).ToString("0");
}
Converting to decimal means you don't need to deal with the 8 different allowed underlying integral types explicitly, as all of them convert losslessly to decimal but not to each other (ulong and long don't convert losslessly between each other but both can handle all the rest). Doing that would probably be faster (esp. if you pick well in your order of comparison), but a lot more verbose for relatively little gain.
Edit:
The above isn't as good as Frankentosh's though, Frankentosh saw through the question to the real problem and solves it very eloquently.
Great stuff ... I have now added an extension method to my project
public static class EnumExtensions
{
public static string NumberString(this Enum enVal)
{
return enVal.ToString("D");
}
}
Now I can get the int value - as a string - by calling Urgency.Routine.NumberString(); Thanks to Frankentosh and Jon :)
a simple approach
((Urgency)4).ToString() // returns "Routine"
You can write an extension method for your specific type:
public static class UrgencyExtension
{
public static string ToIntegerString(this Urgency u)
{
return ((int)u).ToString();
}
}
Use as follows:
Urgency u = Urgency.Routine;
string s = u.ToIntegerString();
How about a little reflection? Should work with all underlying types.
public static class EnumTools
{
public static string ToRawValueString(this Enum e)
{
return e
.GetType()
.GetFields(BindingFlags.Public | BindingFlags.Static)
.First(f => f.Name==e.ToString())
.GetRawConstantValue()
.ToString();
}
}
Then:
Console.WriteLine(Urgency.High.ToRawValueString()); //Writes "2"
If you wanted, you could make the extension method work for all enums:
public static string ToValueString(this Enum enumValue)
{
if (enumValue.GetType().GetEnumUnderlyingType() == typeof(int))
return ((int)(object)enumValue).ToString();
else if (enumValue.GetType().GetEnumUnderlyingType() == typeof(byte))
return ((byte)(object)enumValue).ToString();
...
}

Array index return null instead of out of bound

I am currently trying to implement an "indexed" property within my class definition.
For example I have the following class:
public class TestClass
{
private int[] ids = null;
public string Name { get; set; }
public string Description { get; set; }
public int[] Ids {
get
{
//Do some magic and return an array of ints
//(count = 5 - in this example in real its not fixed)
return _ids;
}
}
}
Now I like to use this class as the following:
private void DoSomething()
{
var testClass = GetSomeTestClass();
//work with the ids
for (int i = 0; i < 10; i++) //I know I could say i < Ids.Length, its just an example
{
int? id = testClass.Ids[i];
//this will result, in a out of bound exception when i reaches 5 but I wish for it to return a null like a "safe" index call ?!?
}
}
So is there a safe index call that results in a null, without the need for me to wrap it again and again in a try catch.
Another thing I dont wish to use the class index, because I need several properties that work like this, with different types (int, string, bool, custom class and so on).
(Again the for is just a simple example, I know I could in this case say "i < Ids.Length")
If you were only interested in already non-nullable type data e.g. struct you could have gotten away with a simple extension method e.g.
public static class ArrayExt
{
public static Nullable<T> GetValueOrNull(this T[] array, int index) where T: struct
{
return array.Length < index ? new Nullable<T>(array[index]) : null;
}
}
which would have allowed you to simply call
int? id = testClass.Ids.GetValueOrNull(i);
However, given you need to support an arbitrary number of types my suggestion would be to implement a wrapper around an array and take control over how you access the data e.g.
public class SafeArray<T>
{
private T[] items;
public SafeArray(int capacity)
{
items = new T[capacity];
}
public object this[int index]
{
get
{
return index < items.Length ? (object)items[index] : null;
}
set
{
items[index] = (T)value;
}
}
}
public class TestClass
{
public TestClass()
{
Ids = new SafeArray<int>(5);
Instances = new SafeArray<MyClass>(5);
}
...
public SafeArray<int> Ids { get; private set; }
public SafeArray<MyClass> Instances { get; private set; }
}
The key to this approach is to use object as the return type. This allows you to cast (or box/unbox if using value types) the data to the expected type on the receiving end e.g.
for (int i = 0; i < 10; i++)
{
// we need an explicit cast to un-box value types
var id = (int?)testClass.Ids[i];
// any class is already of type object so we don't need a cast
// however, if we want to cast to original type we can use explicit variable declarations e.g.
MyClass instance = testClass.Instances[i];
}
OK, whole new approach. Since you have several possible types and want a "joker" method, you can store the values as key/value collection in your class then such method becomes possible.
First, to store the values internally:
public class TestClass
{
private Dictionary<Type, Array> _values = new Dictionary<Type, Array>();
}
Now to populate that collection with actual data:
_values.Add(typeof(int?), new int[] { 1, 2, 3 });
_values.Add(typeof(string), new string[] { "a", "b", "c", "d", "e" });
And finally the joker method:
public T Get<T>(int index)
{
Type type = typeof(T);
Array array;
if (_values.TryGetValue(type, out array))
{
if (index >= 0 && index < array.Length)
{
return (T)array.GetValue(index);
}
}
return default(T);
}
Usage:
for (int i = 0; i < 10; i++)
{
int? id = testClass.Get<int?>(i);
string name = testClass.Get<string>(i);
//...
}
There's really not much else you can do here than just:
if (i >= array.Length) return null;
else return array[i];
or, using the ? operator:
return (i >= array.Length) ? null : array[i];
You could use method instead of property:
public int? Ids(int i) {
if (i >= 0 && i < _ids.length)
{
return _ids[i];
}
return null;
}
from what I have read I see you are implemet a property of an array type, but not an indexer
it is kind of a moveton to fake index out of range situation and it would be still much much better if you take in your code care about out of range. at the end of the day nobody prevent you on assigning a default (in your case NULL) value when range is violated
if you need a shortcut for your the situation you have described above, I would go for the following method in your class:
public int? ReadAtOrNull(int index)
{
return index < ids.Lenght && index > 0 ? (int?)ids[index] : null;
}
People may start complaining that this may be an overhead, but what if you used Skip and FirstOrDefault?
for (int i = 0; i < 10; i++) //I know I could say i < Ids.Length, its just an example
{
int? id = testClass.Ids.Skip(i).FirstOrDefault();
}
Mind you that in this case you may need to declare your array as int?[] otherwise the default value is 0 instead of null.
please Try :
for (int i = 0; i < Ids.Length; i++)
{
if (!String.IsNullOrEmpty(testClass.Ids[i].Tostring())
int? id = testClass.Ids[i];
}
It seems like the think to do here is to use a class index. Here is a direct answer for your TestClass example.
You could also derive your own custom collection class strictly for Ids that stores an int[] internally and overrides all the appropriate access calls I.e) Add, Remove, etc.. (and index the collection like this to make using it easier). Then you could have a property named Ids in your TestClass that behaves like the example.
I know this question is 3 months old but I hope this still helps.
public class TestClass {
private int[] ids = new int[] { 1, 2, 3, 4, 5 };
public string Name { get; set; }
public string Description { get; set; }
public int? this[int index] {
get {
if (index < 0 || index > ids.Length - 1)
return null;
return ids[index];
}
set {
if (value == null)
throw new ArgumentNullException(
"this[index]",
"Ids are not nullable"
);
ids[index] = (int)value;
}
}
}
Usage:
private void DoSomething() {
TestClass testClass = new TestClass();
for (int i = 0; i < 10; i++) {
int? id = testClass[i];
}
// You can assign to the Ids as well
testClass[0] = 6;
}

Check template type and perform respective computation [duplicate]

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 am trying to create a Generic class to handle float and doubles. I need to perform computation according to the type of the variable (float or double), but I am not sure whether the following implementation is the right way to do it. Need some suggestions on it.
// computeFloat is a method of some other class which actually computes and returns a float value
float computeFloat()
{
float a;
....
return a;
}
// setFloat is a method of some other class which actually sets a float value
void setFloat(float val)
{
.....
}
TestClass<T> : IDisposable
{
public void getValue(ref T val)
{
if(val is float)
{
object retVal = computeFloat();
val = (float)retVal;
}
else
{
throw new Exception(" Not implemented");
}
}
public void setValue(T val)
{
if(val is float)
{
object obj = val as object;
float retVal = (float)obj;
setFloat(retVal);
}
else
{
throw new Exception(" Not implemented");
}
}
}
You can look into the following to avoid if statements. You can also consider adding filters on the class to limit it to certain types.
public void getValue(ref T val)
{
object retVal = compute<T>();
val = (T)retVal;
}

How to compare values of two objects in C#

I created a struct
public struct MyCalender : IComparable<MyCalender>
{
public int CompareTo(PersianDate other)
{
return DateTime.Compare(this, other);
}
.
.
.
.
.
}
I new two object of this in a other UserControl, and i want compare they.
I use this code but i get error.
MyCalender value = new MyCalender(2010,11,12);
MyCalender value2 = new MyCalender(2010,11,12);
if (value < value2) ==> geterror
IComparable exposes CompareTo. < and > must be overloaded separately:
class Foo : IComparable<Foo>
{
private static readonly Foo Min = new Foo(Int32.MinValue);
private readonly int value;
public Foo(int value)
{
this.value = value;
}
public int CompareTo(Foo other)
{
return this.value.CompareTo((other ?? Min).value);
}
public static bool operator <(Foo a, Foo b)
{
return (a ?? Min).CompareTo(b) < 0;
}
public static bool operator >(Foo a, Foo b)
{
return (a ?? Min).CompareTo(b) > 0;
}
}
I edited the code so that it does not fail when comparing against null. To keep it brief I used a shortcut that works unless value is Int32.MinValue for a proper Foo. Strictly speaking you'd have to check for null explicitly to get the contract right:
By definition, any object compares greater than (or follows) null, and
two null references compare equal to each other.
Besides, implementing IComparable<T> means that CompareTo(T value) takes a parameter of T. Therefore MyCalendar : IComparable<MyCalender> should implement a method CompareTo(MyCalendar other) rather than PersianDate (or implement IComparable<PersianDate>).
You should either use CompareTo method that you already implemented instead of > in the line you posted or you need to overload > and < operators for your specific class. For instance:
public static bool operator >(MyCalendar c1, MyCalendar c2)
{
return c1.CompareTo(c2) > 0;
}
public static bool operator <(MyCalendar c1, MyCalendar c2)
{
return c1.CompareTo(c2) < 0;
}
But keep in mind that you have to overload both of them.
if comparing just a datetime object,
would something like
DateTime A = DateTime.Now, B = DateTime.Now.AddMinutes(1);
var isqual = A.Date.CompareTo(B.Date);
do the trick?
or something like:
class Calender
{
public DateTime datetime { get; set;}
}
class DateComparer : Calender, IComparable<Calender>
{
public int CompareTo(Calender other)
{
return other.datetime.Date.CompareTo(this.datetime.Date);
}
}

c# syntactic sugar overloading

I have the following method:
virtual public int nonNeg(int? numIn)
{
if ((numIn < 0) || (numIn ==null))
{
return 0;
}
else return (int)numIn;
}
I want to be able to have a single method which could take in either bytes, shorts, or ints to force these values to a nonnegative number. How could I accomplish this?
I would not normally suggest this, but off the top of my head the following overloads should cover most your cases. They will cover the nullable types and the non-nullable types, the compiler will select the appropriate overload.
public static T nonNeg<T>(T n) where T : struct, IComparable
{
if (n.CompareTo(default(T)) <= 0)
{
return default(T);
}
return n;
}
public static T nonNeg<T>(T? n) where T : struct, IComparable
{
if (!n.HasValue || n.Value.CompareTo(default(T)) <= 0)
{
return default(T);
}
return n.Value;
}
Or just use Math.Max( 0, numIn)
Possibly something like this (tested):
virtual public T nonNeg<T>(T numIn) where T : IComparable<T>
{
if (numIn==null){
return default(T);
}
if (Comparer<T>.Default.Compare(numIn,default(T))<0)
{
return default(T);
}
else
return (T)numIn;
}
I think you can do this with:
int negativeNumber = -22;
int nonNegativeNumber = Math.Abs(negativeNumber);
result will be 22
OR
decimal negativeNumber = -22.2;
decimal nonNegativeNumber = Math.Abs(negativeNumber);
result will be 22.2

Categories