I have a method that needs to allow a wide variety of input types. There are two categories of arguments: boundary type arguments, and actual data input arguments.
The boundary arguments are for example, order, frequency, number of points, and number of data points. These boundary arguments are of type int and are common, regardless of the actual data input argument type.
The actual input arguments may be of types: byte, int, short, uint, float, double, decimal, long, etc. To complicate matters further, the actual input data may be individual data, or a list or array of that type. So, the actual input may come as List or uint[], etc. This input is ultimately converted to type double - either as single data or double[].
The method consists of three parts: part one checks the validity of the boundary arguments. This part always applies regardles of the actual input data type. Part two checks and processes the input data arguments. This part changes depending of the type of the input data. Part three performs calculations on the data and is once again common.
I have thought about generic, and I have thought about standard overloading with generics but both seem inefficient. I have come up with what I believe is a workable solution but would appreciate comments: Is my approach computationally efficent, and is there a better way to do this. Your comments would be appreciated.
This is what I currently have:
// ... create lists to store data
static List<double> aList = new List<double>(8);
static List<double> fList = new List<double>(8);
public static double[] MyMethod(int numPts, int numData, object aValue, object fValue)
{
// ... part 1
if (numData < 2) throw new ArgumentOutOfRangeException("numberData must be >= 2.");
if (numPts < 2) throw new ArgumentOutOfRangeException("numberPoints must be >= 2.");
if (numData < numPts) throw new ArgumentOutOfRangeException("numberData must be
>= numPts.");
// ... part 2
if (aValue is byte || aValue is short || aValue is int || aValue is long ||
aValue is float || aValue is double || aValue is decimal ||
aValue is List<byte> || aValue is byte[] || aValue is List<short> ||
aValue is short[] || aValue is List<int> || aValue is int[] ||
aValue is List<float> || aValue is float[] || aValue is List<double> ||
aValue is double[])
{ }
else throw new ArgumentException("a values must be of a numeric type.");
double a = 0.0;
if (aValue is byte || aValue is short || aValue is int || aValue is long ||
aValue is float || aValue is double || aValue is decimal)
{
a = (double)aValue;
// ... store individual values
aList.Add(a);
// ... create the x variable vector
double[] x = aList.ToArray(); // a values
}
else if (aValue is List<byte> || aValue is List<short> || aValue is List<int> ||
aValue is List<float> || aValue is List<double>)
{
// ... get the runtime type of the aValue object
Type t = aValue.GetType();
// ... convert the aValue object to a generic list
IList tmp = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(t));
// ... convert the generic list to a strongly typed list
List<double> aValuesList = tmp.Cast<double>().ToList();
// ... create the x variable vector
double[] x = aValuesList.ToArray(); // a values
}
else
{
// ... process the vector input
// ... get the runtime type of the aValue object
Type t = aValue.GetType();
// ... convert the aValue object to an array
Array tmp = Array.CreateInstance(typeof([]).MakeGenericType(t), aValue.Length);
// ... convert the generic array to a strongly typed array
double[] x = tmp.Cast<double>().ToArray();
}
// ... part 3
{
// ... do calculations
}
}
Just make it accept a double[]. Let the calling code massage their data into the correct format, or provide overloads for the other datatypes.
As an example, if your method is:
public double[] Calculate(double[] aValue, double[] fValue, ...)
{
}
You can provide overloads like:
public double[] Calculate(double aValue, double fValue, ...)
{
return Calculate(new double[]{aValue}, new double[]{fValue}, ...);
}
public double[] Calculate(IEnumerable<double> aValue, IEnumerable<double> fValue, ...)
{
return Calculate(aValue.ToArray(), fValue.ToArray(), ...);
}
To cover other datatypes you can reduce the number of overloads by using something like:
public double[] Calculate<T>(T aValue, T fValue) where T : IConvertible
{
return Calculate(aValue.ToDouble(), fValue.ToDouble(), ...);
}
public double[] Calculate<T>(IEnumerable<T> aValue, IEnumerable<T> fValue) where T : IConvertible
{
return Calculate(aValue.Select(x=>x.ToDouble()), fValue.Select(x=>x.ToDouble()), ...);
}
This should cover all other primitive data types, which is all of your example.
If you do this, the code in your calculate method is reduced down to:
public double[] Calculate(double[] aValue, double[] fValue, int numData, int numPts)
{
if (numData < 2) throw new ArgumentOutOfRangeException("numberData must be >= 2.");
if (numPts < 2) throw new ArgumentOutOfRangeException("numberPoints must be >= 2.");
if (numData < numPts) throw new ArgumentOutOfRangeException("numberData must be
>= numPts.");
// do calculation
}
... which is a lot simpler.
You really don't want to do that.
Since your input is quite complex, and with many checks, you should put all of it into a class that will take care of all the checks. The various types of inputs just beg to become derived classes.
I think a bunch of overloads would be the way to go. Each one would be fairly simple, just calling the main method. But then all of your data type testing is done by the compiler, rather than by your huge if statements. You could also set a flag in each overload to tell your main method if you received a single number, a List<> or an array (or whatever else you need to handle). For example:
enum DataType { SingleNumber, NumberList, NumberArray }
// one of many overloads
public static double[] MyMethod(int numPts, int numData, byte aValue, object fValue) {
return MyMethod(numPts, numData, (object)aValue, fValue, DataType.SingleNumber);
}
You have 2 stages there... First you're checking everything, and then aValue separately.
So, separate it.
Then you can use generics to call the specific function for the aValue type
void foo<T> (T aValue) where T : struct { } //value type
void foo<T> (List<T> aValue) where T : struct { } //List of value type
void foo<T> (T[] aValue) where T : struct { } //Array of value type
If you wan a better constraint for numeric types: Generic constraint to match numeric types
If you don't want to require the caller to convert its data to a double[] then by all means do it in the callee. But please delegate it to another function! It's much easier to read what's going on:
public static double[] MyMethod(int numPts, int numData, object aValue, object fValue)
{
//validation omitted for brevity
// ... part 2
double[] aValues = ToDoubleArray(aValue);
// ... the rest
}
Done!
Here's an implementation, though there's doubtless a more robust and/or efficient one:
private double[] ToDoubleArray(object aValue)
{
if (aValue is byte || aValue is short || aValue is int || aValue is long
|| aValue is float || aValue is double || aValue is decimal)
return new double[] { Convert.ToDouble(aValue) };
if (aValue is IEnumerable)
return ((IEnumerable)aValue).Select(Convert.ToDouble).ToArray();
throw new ArgumentException("The value was of an unsupported type", "aValue");
}
Done!
Related
I'm new to C#, coming from Java, and I'd like to check whether a certain object is a Number (it can be an Integer, Double, Float, etc). In Java I did this by saying if (toRet instanceof Number). I'm hoping there's a similar C# thing like if (toRet is Number) but thus far I haven't been able to find a Number class that does this. Is there a way to do this, or do I have to manually check for Integer, Double, etc?
Edit for more info: Basically what I want to do is eventually have a byte array. However, when the array is stored in a text file, the parser I'm using can sometimes think it's an integer array or a double array. In Java, I had this:
JSONArray dblist = (JSONArray)result_;
byte[] reallyToRet = new byte[dblist.size()];
Object toComp = dblist.get(0);
if (toComp instanceof Number)
for (int i=0; i < dblist.size(); ++i) {
byte elem = ((Number) dblist.get(i)).byteValue();
reallyToRet[i] = elem;
}
return reallyToRet;
}
The important bit here is the if statement. Sometimes the objects in dblist would parse as integers, sometimes as doubles, and only rarely as bytes, but all I really care about at the end is the byte value.
Well, yeah, but it's an extension method that just ORs all the possibilities.
This is it:
public static bool IsNumber(this object value)
{
return value is sbyte
|| value is byte
|| value is short
|| value is ushort
|| value is int
|| value is uint
|| value is long
|| value is ulong
|| value is float
|| value is double
|| value is decimal
|| value is BigInteger;
}
and you would use it like this:
if (toRet.IsNumber());
This needs to be in a static class.
I am not sure about any class for that. But you can check for instance, for integer see
int val;
if(Int32.TryParse(integer, out val))
else
Unlikely, you can use Double.TryParse(number, out val) etc.
I am trying to build a method that will take a variety of numeric types and preprocess them for a second method. I am not sure if I should be simply overloading or using a generic method. I tried to use a generic method but the method does not seem to recognize the parameter type. The code is below. Can someone please explain to me whether it is better to overload or use a generic method in this case? Also, if I wanted to use a generic method to do this, how could I make it work? Thank you very much.
public static class math
{
public static int nextpow2<T>(T a)
{
double w;
if ( a.GetType() is sbyte ||
a.GetType() is byte ||
a.GetType() is short ||
a.GetType() is ushort ||
a.GetType() is int ||
a.GetType() is uint ||
a.GetType() is long ||
a.GetType() is ulong ||
a.GetType() is float ||
a.GetType() is double ||
a.GetType() is decimal
) w = (double)Convert.ChangeType(a, typeof(double));
else
throw new System.ArgumentException("Internal error in nextpow2: argument a is not a number!");
return _nextpow2(w);
}
private static int _nextpow2(double a)
{
double index = Math.Abs(a);
int p = (index > 1) ? (int)Math.Ceiling( Math.Log( index, 2.0) ) : 0;
return p;
}
I am calling the method as follows:
int indx = 0;
int p = math.nextpow2(indx);
The code fails to compile. I get the following error:
Internal error in nextpow2: argument a is not a number!
Can someone please explain what I am doing wrong? Thank you.
Can someone please explain what I am doing wrong?
Sure. You're checking whether a Type object is an sbyte, or a byte, etc. You're not checking whether the type represents the type of sbyte etc... you're asking whether the value is an sbyte. That's never, ever the case. (Which is why you're getting a compile-time error.)
You could use:
if (a.GetType() == typeof(byte) ||
// etc)
But I probably wouldn't. I wouldn't make this a generic method at all. If you really want the functionality, I'd write:
private static readonly HashSet<Type> ValidTypes = new HashSet<Type>
{
typeof(sbyte), typeof(byte), /* etc */
};
public static double ConvertToDouble(object x)
{
if (x == null)
{
throw new ArgumentNullException("x");
}
if (!ValidTypes.Contains(x.GetType())
{
throw new ArgumentException("...");
}
return Convert.ChangeType(x, typeof(double));
}
Note how this is doing one thing: converting the argument to double. There's no point in making it then call _nextpow2 - it's easy enough for the caller to do that if they want to.
Additionally, you've written two contradictory things:
The code fails to compile. I get the following error:
Internal error in nextpow2: argument a is not a number!
If it fails to compile (which is what I'd expect, btw) then you can't be running the code, which means you can't be getting the exception. You need to differentiate between compile-time errors like this:
warning CS0184: The given expression is never of the provided ('sbyte') type
and execution-time exceptions.
Also, both your class and method names violate normal .NET naming conventions.
You can either say
a is sbyte
or say
a.GetType() == typeof(sbyte)
but it makes no sense to mix it into a.GetType() is sbyte. You should get a compiler warning about that! For a.GetType() will be an object which derives from System.Type (actually it will be System.RuntimeType), and therefore it can never derive from sbyte (since sbyte is sealed, being a struct, and sbyte itself derives only from ValueType and Object).
A better solution than a generic method, is to have:
public static int Nextpow2(double a)
{
...
}
All numereric types except decimal are implicitly convertible to double. So with the above signature, you can use it the way you want:
int indx = 0;
int p = math.Nextpow2(indx);
This pattern comes up very frequently in my code:
x= x== 0? 1: x;
//or
x= x==null? 1: x;
However it happens that sometimes x is a long expression and I'd have to use intermediate variables. That's just useless boilerplate code. I can cook up a method and call it instead:
Util.IfNullOrZero(x, 1);
But that's just ugly. What is the best way of expressing the pattern? In ruby there is such syntax for when x is nil which gets rid of redundant x's:
x||= 1
I could extend object in a manner
public static class wtf
{
public static T Default<T>(this object o, T d)
{
return o == null ? d : new object[] { o }.Cast<T>().First();
}
}
And then do
object param= null;
int x= param.Default(1);
But that's a bit expensive.
In short how to best make C# do x||= 1 like in ruby?
Update
This is what I cooked up. I'm currently looking for a faster way of using the Template parameter to convert object to T.
public static class MyExtensions
{
public static T d<T>(this object o, T d)
{
return o == null || o.Equals(default(T)) ? d : new object[] { o }.Cast<T>().First();
}
}
In fact the code does three things at once: Casts to default type, checks for default value and also checks for null.
Update 2
return o == null || o.Equals(default(T)) ? d : (T)o; // much simpler and faster
I still think it is a commonality which needs to be included in core language.
Update 3
This is what I finally wrote, taking into account DataTable DBNull types.
public static T d<T>(this object o, T d)
{
return o == null || (o is System.DBNull) || o.Equals(default(T)) ? d : (T)Convert.ChangeType(o, typeof(T));
}
For handling the "==null" case, the null coalesce operator does the trick.
y = x ?? z;
means
if (x == null)
y = z;
else
y = x;
I'm not aware of something that check for both zero and null, writing a method to perform this task might be the best solution. Here it goes:
public static T IsNullOrZero<T>(this T variable, T defaultValue)
{
// defaultValue can't be null, doesn't make sense
if (defaultValue == null) throw new ArgumentException("default value can't be null", "defaultValue");
if (variable == null || variable.Equals(default(T)))
return defaultValue;
return variable;
}
Usage:
x = x.IsNullOrZero(y);
Note: this in fact works on non-numbers too (name might be misleading if dealing with non-numbers... maybe something along the lines of IsNullOrDefault might be a better name).
You can check like
public static bool IsNullOrValue(this int? value, int valueToCheck)
{
return (value??valueToCheck) == valueToCheck;
}
more on here
For checking for null and providing a default value, you can use the ?? operator:
return x ?? new Foo();
That means, if x is null, return new Foo(), else return x. You can use it for reference types and nullable types. For nun-nullable types like int, you still need to explicitly check for 0.
What you want is the Coalesce operator (??), which does just that - if returns the first operand if it's not null, and the second if it is. This will instantiate a new object if the current one is null:
return myObj ?? new MyObject();
Note that the ?? operator works only for classes and reference types, not for ints and other value types that can't be null. There, you'll have to check manually for default, uninitialized values (0 for ints and shorts and stuff, false for bools, and so forth)
I've got a generic type T. Using Marc's Operator class I can perform calculations on it.
Is it possible to detect by mere calculations whether the type is an integral or a nonintegral type?
Perhaps there is a better solution? I'd prefer to support any possible type, so I'd like to prevent hard-coding which types are integral/nonintegral.
Background info
The situation I find myself in is I want to cast a double to T but round to the nearest value of T to the double value.
int a = (int)2.6 results in 2 while I want it to result it in 3, without knowing the type (in this case int). It could also be double, in which case I want the outcome to be 2.6.
Have you tried Convert.ChangeType? Something like:
Convert.ChangeType(1.9d, typeof (T))
It will work for all numeric types I think (as long as the first parameter is iConvertible and the type is a supported one which all basic numerics should be I believe).
Its important to mention that this will call something like double.ToInt32 which rounds values rather than truncates (bankers rounding I believe).
I tested this in a little LinqPad program and it does what I think you want:
void Main()
{
var foo = RetNum<decimal>();
foo.Dump();
}
public static T RetNum<T>()
{
return (T)Convert.ChangeType(1.9d, typeof (T));
}
Here's a method which will determine if a particular value stored in a generic numeric type is an integer without hardcoding. Tested working for me on .NET 4. Correctly handles all built in numeric types (as defined in the MSDN link at the bottom) except BigInteger, which doesn't implement IConvertible.
public static bool? IsInteger<T>(T testNumber) where T : IConvertible
{
// returns null if T is non-numeric
bool? isInt = null;
try
{
isInt = testNumber.ToUInt64(CultureInfo.InvariantCulture) == testNumber.ToDouble(CultureInfo.InvariantCulture);
}
catch (OverflowException)
{
// casting a negative int will cause this exception
try
{
isInt = testNumber.ToInt64(CultureInfo.InvariantCulture) == testNumber.ToDouble(CultureInfo.InvariantCulture);
}
catch
{
// throw depending on desired behavior
}
}
catch
{
// throw depending on desired behavior
}
return isInt;
}
Here's a method which will determine whether a particular type is an integral type.
public static bool? IsIntegerType<T>() where T : IConvertible
{
bool? isInt = null;
try
{
isInt = Math.Round((double)Convert.ChangeType((T)Convert.ChangeType(0.1d, typeof(T)),typeof(double)), 1) != .1d;
// if you don't round it and T is float you'll get the wrong result
}
catch
{
// T is a non numeric type, or something went wrong with the activator
}
return isInt;
}
Convert.ChangeType is the way to convert, with rounding, between two generic numeric types. But for kicks and curiosity, here's a way to convert a generic numeric type to an int, which could be extended to return a generic type without too much difficulty.
public static int GetInt32<T>(T target) where T : IConvertible
{
bool? isInt = IsInteger<T>(target);
if (isInt == null) throw new ArgumentException(); // put an appropriate message in
else if (isInt == true)
{
try
{
int i = target.ToInt32(CultureInfo.InvariantCulture);
return i;
}
catch
{ // exceeded size of int32
throw new OverflowException(); // put an appropriate message in
}
}
else
{
try
{
double d = target.ToDouble(CultureInfo.InvariantCulture);
return (int)Math.Round(d);
}
catch
{ // exceeded size of int32
throw new OverflowException(); // put an appropriate message in
}
}
}
My results:
double d = 1.9;
byte b = 1;
sbyte sb = 1;
float f = 2.0f;
short s = 1;
int i = -3;
UInt16 ui = 44;
ulong ul = ulong.MaxValue;
bool? dd = IsInteger<double>(d); // false
bool? dt = IsInteger<DateTime>(DateTime.Now); // null
bool? db = IsInteger<byte>(b); // true
bool? dsb = IsInteger<sbyte>(sb); // true
bool? df = IsInteger<float>(f); // true
bool? ds = IsInteger<short>(s); // true
bool? di = IsInteger<int>(i); // true
bool? dui = IsInteger<UInt16>(ui); // true
bool? dul = IsInteger<ulong>(ul); // true
int converted = GetInt32<double>(d); // coverted==2
bool? isd = IsIntegerType<double>(); // false
bool? isi = IsIntegerType<int>(); // true
Additionally, this MSDN page has some example code which might be helpful. Specifically, it includes a list of types considered to be numeric.
I'm not 100% sure what you're asking, but:
To check if it's an integral type, use this: if (obj is float || obj is double), or if typeof(T) == typeof(float) || typeof(T) == typeof(double))
To check if it's an integral value, cast it to a double, and then do if(value == Math.Round(value))
Of course, that is assuming that you have a number in the first place. I believe that the Operator class you're using supports things like DateTime. Would it be better to make your generic method have a generic constraint where T : IConvertible? That way there'd be explicit ToDouble and ToInteger methods.
Edit:
I think I understand: you've got two local variables, double d; T num;. You want to cast d to type T, but with proper rounding if T is a integral type. Is that correct?
Assuming that's correct, here's what I'd do:
public void SomeMethod<T>()
{
double d;
// I think I got all the floating-point types. There's only a few, so we can test for them explicitly.
if(typeof(T) != typeof(double) && typeof(T) != typeof(float) && typeof(T) != typeof(Decimal))
{
d = Math.Round(d);
}
T converted = Convert.ChangeType(d, typeof(T));
}
Chris's answer gives a possible solution to the scenario I mentioned, but for performance reasons I am still attempting to answer the actual question.
The assumption (untested) is, Convert.ChangeType is much slower than Math.Round(). Ideally, I can check one time whether the given type is integral or not, and conditionally call Math.Round() from then on to obtain a much more efficient solution than calling Convert.ChangeType() constantly.
I'm attempting the following implementation:
Convert both 3, 2 and 1 to the desired unknown type. (This assumes a conversion from an int to the numeric type is possible, which should always be possible anyhow.)
In case 3 / 2 == 1, it is an integral type. Otherwise, it is a nonintegral type.
This solution doesn't rely anywhere on knowing the type and solely uses conversions and calculations.
I have a list of objects, some of which can be null. I want it sorted by some property, with nulls at the end of list. However, List<T>.Sort() method seems to put nulls in the beginning no matter what the comparer returns. This is a little program that I used to test this:
class Program
{
class Foo {
public int Bar;
public Foo(int bar)
{
Bar = bar;
}
}
static void Main(string[] args)
{
List<Foo> list = new List<Foo>{null, new Foo(1), new Foo(3), null, new Foo(100)};
foreach (var foo in list)
{
Console.WriteLine("Foo: {0}", foo==null?"NULL":foo.Bar.ToString());
}
Console.WriteLine("Sorting:");
list.Sort(new Comparer());
foreach (var foo in list)
{
Console.WriteLine("Foo: {0}", foo == null ? "NULL" : foo.Bar.ToString());
}
Console.ReadKey();
}
class Comparer:IComparer<Foo>
{
#region Implementation of IComparer<in Foo>
public int Compare(Foo x, Foo y)
{
int xbar = x == null ? int.MinValue : x.Bar;
int ybar = y == null ? int.MinValue : y.Bar;
return ybar - xbar;
}
#endregion
}
}
Try this yourself: sorted list is printed as
Foo: NULL
Foo: NULL
Foo: 100
Foo: 3
Foo: 1
nulls Are first, even though they're compared as int.Minvalue. Is the method buggy or what?
Your implementation is incorrect because you failed to write the specification first, then write code that meets the specification.
So, start over. Write a specification:
FooCompare takes two references to Foo, x and y. Either may be null.
IComparer.Compare(x,y) is documented as returning zero if x and y are equal, negative if y is greater than x, and positive if y is smaller than x. We will follow this convention.
if x and y are both null, they are equal.
if one is null and the other one is not then the null one is the smaller.
if neither are null then the comparison is based on the value of the Bar property.
And now you can write code that you are guaranteed matches the spec:
// FooCompare takes two references to Foo, x and y. Either may be null.
// +1 means x is larger, -1 means y is larger, 0 means they are the same.
int FooCompare(Foo x, Foo y)
{
// if x and y are both null, they are equal.
if (x == null && y == null) return 0;
// if one is null and the other one is not then the non-null one is larger.
if (x != null && y == null) return 1;
if (y != null && x == null) return -1;
// if neither are null then the comparison is
// based on the value of the Bar property.
var xbar = x.Bar; // only calculate x.Bar once
var ybar = y.Bar; // only calculate y.Bar once
if (xbar > ybar) return 1;
if (ybar > xbar) return -1;
return 0;
}
// The original poster evidently wishes the list to be sorted from
// largest to smallest, where null is the smallest.
// Reverse the polarity of the neutron flow:
int Compare(Foo x, Foo y)
{
return FooCompare(y, x);
}
Don't mess around with clever integer arithmetic tricks; as you've seen, clever equals buggy. Correctness first.
Let’s say x is null and y is 1.
int xbar = x == null ? int.MinValue : x.Bar;
int ybar = y == null ? int.MinValue : y.Bar;
return ybar - xbar;
So now we have 1 - int.MinValue. This will be an overflow, so the end result will be negative, hence the null will be considered less than 1.
For that reason, the computation is fundamentally flawed.
public int Compare(Foo x, Foo y)
{
int xbar = x == null ? int.MinValue : x.Bar;
int ybar = y == null ? int.MinValue : y.Bar;
return ybar.CompareTo(xbar);
}
(Thanks to the commenters for pointing out the flaw in my method.)
Replace this line:
return ybar - xbar;
with this line:
return ybar.CompareTo(xbar);
Because your arithmetic is overflowing.
Your implementation of IComparer.Compare is unnecessarily complex. Remember that all that matters about the return value is the sign - the magnitude is unimportant. To have nulls compare less than all real Foos, simply defer to Int32s implementation of CompareTo, after making your substitution:
return (x == null ? int.MinValue : x.Bar)
.CompareTo((y == null ? int.MinValue : y.Bar))
int.MinValue is -2147483648.
Now, suppose you were comparing 3 and -2147483648 via subtraction, specifically 3 - (-2147483648?
Also you should consider using the null coalescing operator ??