C# object equals int doesn't equal true - c#

I have a very simple if statement but it always returns false never true.
Here is my if statement
if (objectValue.Equals(intValue))
{
return true;
}
return false;
Do I need to cast my objectValue variable to an int before comparing them?

Since Equals is a virtual method it will call the appropriate method of the subclass of object. In this case int.Equals. In a very simple example:
object o = 4;
int i = 4;
o.Equals(i) returns true. So your problem is somewhere else. Maybe objectValue is not an int, but a byte, short or other numerical type.

The problem isn't with having the int boxed in an object - that works just fine, as you can easily try yourself.
The problem only appears when the object doesn't actually contain an int, but rather a different numerical type, e.g. short or byte - in that case, you have to first unbox it to the correct type (for example, (short)objectValue) and then do the comparison. Unboxing a boxed short to int results in InvalidCastException - you have to use the exact type with value-types.
Also, there's usually no need to use Equals for that - just do (int)objectValue == intValue or so.

int val;
if (int.TryParse(objectValue.ToString(), out val))
{
if (val == intValue)
{
// return true;
}
else
{
//return false;
}
}
else
{
// value of obj is not int. you know here something is wrong
}
Using TryParse() method would be safer option even if you have non int value in the objectValue.

Yes you need to cast it
return ((int)objectValue).Equals(intValue);
without the cast a type comparison will be performed and object is never equal to an int, thats why you get the false value.

Related

Can I cast an integer to a long when the types are generic/boxed?

The method below looks for a particular key in a dictionary and attempts to safely store it in destination if it can. The problem I am running into is when T=Int64 and the item in the dictionary is Int32 or UInt32 (both of which can fit inside an Int64 without data loss). valueAsObject is T returns false when T is Int64 and valueAsObject is Int32.
Is it possible to safely cast valueAsObject to T without just trying it and catching any exceptions? I would like to avoid exceptions, though if that is the only way I can make it work.
public static void MyMethod<T>(IDictionary<String, Object> dictionary, String key, ref T destination)
{
if (!dictionary.ContainsKey(key))
return;
var valueAsObject = dictionary[key];
if (!(valueAsObject is T))
return;
destination = (T)valueAsObject;
}
Basically, I want the function to do nothing (return) if the thing found in the dictionary can not be safely stored in a type T variable (without data loss), otherwise it should cast it as necessary and store it.
This is not built-in at the language or runtime level. You can use Convert.ChangeType to perform the conversion. This method also performs lossy conversions so you probably have to build your own conversion logic (which will involve casts and be ugly).
You can't just do something like this?
public static void MyMethod<T>( IDictionary<string,object> dictionary , string key , ref T destination )
{
object value ;
bool found = dictionary.TryGetValue( key , out value ) ;
if (found && value is T)
{
destination = (T) value ;
}
return;
}
The is operator:
evaluates to true if the provided expression is non-null, and the provided object
can be cast to the provided type without causing an exception to be thrown.
.
.
.
Note that the is operator only considers reference conversions, boxing conversions,
and unboxing conversions. Other conversions, such as user-defined conversions, are not considered.
Basically, if the object directly inherits from the specified type, or implements the type (if T is an interface), is should return true and you should be able to down-cast the object to your type T.
If, however, you need to worry about user-defined conversion operators, you'll need to reflect over the object's type and over typeof(T) to see if a user-defined conversion operator is defined on either type that will convert the object to a compatible type. Getting that right is likely to be...tricky.
This is the final solution I went with. It came from a number of comments and other answers so I encourage reading the other answers/comments for additional details as to why this was necessary:
private static void GetFromDictionary<T>(IDictionary<String, Object> dictionary, String key, ref T outputLocation)
{
if (!dictionary.ContainsKey(key))
return;
var valueAsObject = dictionary[key];
if (!CanBeCastTo<T>(valueAsObject))
return;
outputLocation = (T)Convert.ChangeType(valueAsObject, typeof(T));
}
private static bool CanBeCastTo<T>(Object thingToCast)
{
if (thingToCast is T)
return true;
var tType = typeof(T);
if (tType == typeof(Int64) && thingToCast is Int32)
return true;
if (tType == typeof(Double) && thingToCast is Decimal)
return true;
return false;
}
In my case, I only needed to handle a certain subset of primitive types (Int32, Int64, String, Double, Decimal) and I was willing to accept lossy conversion of Decimal to Double.
The take away here is that the "is" operator will return false for primitives even if it can fit without loss (Int32 in Int64). Also, (T)valueAsObject will not do an explicit typecast. So if valueAsObject is of type Int32 and T is of type Int64 the above will throw an exception even though (Int64)valueAsObject is valid. This one bit me but luckily #usr suggested using Convert.ChangeType which handles the problem.
Optimizations could be made to the above code but I chose to leave it as is for readability.

How to check whether a (generic) number type is an integral or nonintegral type in C#?

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.

Why a.compareTo(b) is equal to compareTo(a,b) or a.method(b) = method(a,b)?

As i am new to C# programming language i am a little confused about C# syntax.
A method which can get two values to compare those two values can be written as a.compareTo(b) instead of compareTo(a,b) How is it possible?
Assuming that compareTo returning an int the variable a is chained to int and gets compared! How?
Thank you in advance.
In C#, the int keyword actually represents a structure of type System.Int32. This type has several methods available on it, one of those being CompareTo(Int32) as you have seen.
CompareTo for an Int32 object takes in an integer value, compares that value to itself and returns the result, very simply like this:
public int CompareTo(int value)
{
if (this < value)
{
return -1;
}
if (this > value)
{
return 1;
}
return 0;
}
The this keyword refers to the current instance of the Type that this method belongs to, in your case a.
The documentation for Int32 and its methods can be found here.
As per documentation:
This method is only a definition and must be implemented by a specific class or value type to have effect. The meaning of the comparisons specified in the Return Value section ("precedes", "occurs in the same position as", and "follows") depends on the particular implementation.
In the example, they compare temperatures by its Fahrenheit value which is a double:
public int CompareTo(object obj) {
if (obj == null) return 1;
Temperature otherTemperature = obj as Temperature;
if (otherTemperature != null)
return this.temperatureF.CompareTo(otherTemperature.temperatureF);
else
throw new ArgumentException("Object is not a Temperature");
}
But in your own class, you can decide how to compare one instance of it against another.

cannot convert type 'string' to 'int?' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion or null type conversion

C# accepts the following:
object o = "hello";
int? i = o as int?;
if (i == null) {
// o was not a boxed int
}
else {
// Can use i.Value to recover the original boxed value
}
But not
String o = "hello";
int? i = o as int?;
if (i == null) {
// o was not a boxed int
}
else {
// Can use i.Value to recover the original boxed value
}
I'm just wondering about the behaviour of the keyword as in C#.
The same as in Java this would fail:
Object test1 = "hello";
Integer test2 = (Integer) test1;
String test3 = "hello";
Integer test4 = (Integer) test3; //compilation error
The compiler knows that a string can never be an int? so it tells you that. That doesn't mean that int? isn't useful. Your attempted use case is far from the normal one. The normal one is "I want to represent an integer and the possibility that the value is missing/unknown". For that, int? works extremely well.
Why would you expect your original code to work? Why would it be helpful?
Note that you can use as with nullable types, for unboxing:
object o = "hello";
int? i = o as int?;
if (i == null)
{
// o was not a boxed int
}
else
{
// Can use i.Value to recover the original boxed value
}
EDIT: Having seen your comment, you don't use as to parse things. You probably want to use int.TryParse:
string text = "123":
int value;
if (int.TryParse(text, out value))
{
Console.WriteLine("Parsed successfully: {0}", value);
}
else
{
Console.WriteLine("Unable to parse text as an integer");
}
If you're sure the string is meant to be an integer (i.e. it's a bug otherwise) then you can just use int.Parse:
int value = int.Parse(text);
That will throw an exception if the parsing fails.
Note also that both of these methods allows you to specify a format provider (usually a culture info) which allows you to express how numbers are expressed in that format (e.g. thousands separators).
EDIT: In answer to your new question, the compiler prevents this because it knows a string can't possibly be a boxed int - the conversion will never ever succeed. When it only knows that the original value is an object, it might succeed.
For instance, suppose I said to you, "Here's a shape: is it a square?" That's a sensible question. It's reasonable to ask it: you can't tell without looking at the shape.
If, however, I said: "Here's a triangle: is it a square?" Then you'd be reasonably entitled to laugh in my face, as a triangle can't possibly be a square - the question doesn't make sense.
int? means a nullable integer type, not an int that could contain any other type of variable.
If you want a variable type that could contain an int or a string, you'd have to use an object, or a string I suppose, and then live a life filled with type casting. I don't know why you would want to do that, though.
int? allows you to store any integer value, or a null value. Which is useful when say the answer to the question "How many orders has this person placed" is legitimately "I don't know" instead of a number of orders, or zero which would be "I know for a fact this person has never placed an order".
I want to add some further information.
An other case, why the cast is invalid and the compiler throws an error on compilation is, that System.String is marked as sealed. So the compiler knows from which types System.String inherites and to which types you can cast the string using the as-operator.
Due to the keyword sealed, the compiler also knows that you cannot inherit from System.String to add functionality or implement some additional interfaces.
The code below is an example and the compiler will throw the following error on compilation
Cannot convert type 'SealedClass' to
'ICastToInterface' via a reference
conversion, boxing conversion,
unboxing conversion, wrapping
conversion, or null type conversion
public class UnsealedClass {
// some code
}
public sealed class SealedClass {
// some code
}
public interface ICastToInterface {
// some code
}
public class Test {
public Test() {
UnsealedClass unsealedClass = new UnsealedClass();
SealedClass sealedClass = new SealedClass();
ICastToInterface unsealedCast = unsealedClass as ICastToInterface; // This works fine
ICastToInterface sealedCast = sealedClass as ICastToInterface; // This won´t compile, cause SealedClass is sealed
}
}
but you can check the value of null and set it to null.
int? blah;
if (blah == null)
{}
int? is a nullable integer, it has nothing to do with casting and the as keyword. "String" is a string type object, which is not convertible to an int (nullable or non-nullable).
The as Keyword is virtually the same as casting using brackets except it will not return an error, it will set the object to null:
int i = 1;
object o = i; //boxing
int j = (int)o; //unboxing
This first example works as the object assigned to o is an int.
Now consider:
string i = "MyString";
object o = MyString;
int j = (int)o //unboxing raises exception
int j = o as int; //raises compilation Error as int is not nullable
int? j = o as int?; /// o == null
I hope that that helps to explain the difference between the two concepts.
Richard

Better way to cast object to int

This is probably trivial, but I can't think of a better way to do it. I have a COM object that returns a variant which becomes an object in C#. The only way I can get this into an int is
int test = int.Parse(string.Format("{0}", myobject))
Is there a cleaner way to do this? Thanks
You have several options:
(int) — Cast operator. Works if the object already is an integer at some level in the inheritance hierarchy or if there is an implicit conversion defined.
int.Parse()/int.TryParse() — For converting from a string of unknown format.
int.ParseExact()/int.TryParseExact() — For converting from a string in a specific format
Convert.ToInt32() — For converting an object of unknown type. It will use an explicit and implicit conversion or IConvertible implementation if any are defined.
as int? — Note the "?". The as operator is only for reference types, and so I used "?" to signify a Nullable<int>. The "as" operator works like Convert.To____(), but think TryParse() rather than Parse(): it returns null rather than throwing an exception if the conversion fails.
Of these, I would prefer (int) if the object really is just a boxed integer. Otherwise use Convert.ToInt32() in this case.
Note that this is a very general answer: I want to throw some attention to Darren Clark's response because I think it does a good job addressing the specifics here, but came in late and wasn't voted as well yet. He gets my vote for "accepted answer", anyway, for also recommending (int), for pointing out that if it fails (int)(short) might work instead, and for recommending you check your debugger to find out the actual runtime type.
The cast (int) myobject should just work.
If that gives you an invalid cast exception then it is probably because the variant type isn't VT_I4. My bet is that a variant with VT_I4 is converted into a boxed int, VT_I2 into a boxed short, etc.
When doing a cast on a boxed value type it is only valid to cast it to the type boxed.
Foe example, if the returned variant is actually a VT_I2 then (int) (short) myObject should work.
Easiest way to find out is to inspect the returned object and take a look at its type in the debugger. Also make sure that in the interop assembly you have the return value marked with MarshalAs(UnmanagedType.Struct)
Convert.ToInt32(myobject);
This will handle the case where myobject is null and return 0, instead of throwing an exception.
Use Int32.TryParse as follows.
int test;
bool result = Int32.TryParse(value, out test);
if (result)
{
Console.WriteLine("Sucess");
}
else
{
if (value == null) value = "";
Console.WriteLine("Failure");
}
Maybe Convert.ToInt32.
Watch out for exception, in both cases.
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;
I am listing the difference in each of the casting ways. What a particular type of casting handles and it doesn't?
// object to int
// does not handle null
// does not handle NAN ("102art54")
// convert value to integar
int intObj = (int)obj;
// handles only null or number
int? nullableIntObj = (int?)obj; // null
Nullable<int> nullableIntObj1 = (Nullable<int>)obj; // null
// best way for casting from object to nullable int
// handles null
// handles other datatypes gives null("sadfsdf") // result null
int? nullableIntObj2 = obj as int?;
// string to int
// does not handle null( throws exception)
// does not string NAN ("102art54") (throws exception)
// converts string to int ("26236")
// accepts string value
int iVal3 = int.Parse("10120"); // throws exception value cannot be null;
// handles null converts null to 0
// does not handle NAN ("102art54") (throws exception)
// converts obj to int ("26236")
int val4 = Convert.ToInt32("10120");
// handle null converts null to 0
// handle NAN ("101art54") converts null to 0
// convert string to int ("26236")
int number;
bool result = int.TryParse(value, out number);
if (result)
{
// converted value
}
else
{
// number o/p = 0
}
There's also TryParse.
From MSDN:
private static void TryToParse(string value)
{
int number;
bool result = Int32.TryParse(value, out number);
if (result)
{
Console.WriteLine("Converted '{0}' to {1}.", value, number);
}
else
{
if (value == null) value = "";
Console.WriteLine("Attempted conversion of '{0}' failed.", value);
}
}
Strange, but the accepted answer seems wrong about the cast and the Convert in the mean that from my tests and reading the documentation too it should not take into account implicit or explicit operators.
So, if I have a variable of type object and the "boxed" class has some implicit operators defined they won't work.
Instead another simple way, but really performance costing is to cast before in dynamic.
(int)(dynamic)myObject.
You can try it in the Interactive window of VS.
public class Test
{
public static implicit operator int(Test v)
{
return 12;
}
}
(int)(object)new Test() //this will fail
Convert.ToInt32((object)new Test()) //this will fail
(int)(dynamic)(object)new Test() //this will pass
You can first cast object to string and then cast the string to int;
for example:
string str_myobject = myobject.ToString();
int int_myobject = int.Parse(str_myobject);
this worked for me.
int i = myObject.myField.CastTo<int>();
This worked for me, returning 0 also when myobject contains a DBNull
int i = myobject.ToString().Cast<int>().FirstOrDefault();

Categories

Resources