سؤال

Here's a weird one I ran into. I've got a function that returns an object. In a particular case, I know for sure that object is an int, but another function calling this function requires a float. The only way I could get this to work was the following:

private object parser(string expr) {...}

private float parseFloat(string expr)
{
    ...
    object result = parser(expr);
    if (result is int)
        return (float)(int)result;
    else
        return (float)result;
}

Without that type-check, I couldn't get it to work at all, even though I knew the result of the parser function in this case was an int. (You could see it in the debugger.) I'd prefer the line to go simply:

private float parseFloat(string expr)
{
    ...
    return (float)parser(expr);
}

(Type checking is done beforehand, and parseFloat should never be called with an expression that will not evaluate to a float or int.) Is there some reason why it's necessary to double-cast this variable? I obviously don't want to double-cast it in all cases, because if the return from parser was a float, it would truncate it to int first and we don't want that. (And yes, I tried replacing float and int with Single and Int32, etc. Didn't make any difference.)

I saw this question, but it depends on knowing the type in advance, and the only solution it offers is this double-casting trick, which in my case would truncate floats unless I do a type-check first, which also requires an additional local variable to hold the result. Is there any way to avoid that extra step?

هل كانت مفيدة؟

المحلول

When you unbox a value type that has been put into an object box, you must use the correct cast. The conversion from one numeric type to another is an extra cast that comes after the unboxing.

In your case, however, the second cast is really implicit, so you could simplify a little bit to:

if (result is int)
    return (int)result;
else
    return (float)result;

Why do you have boxed value types in the first place? If you don't know what type is boxed, to unbox you will normally have to check with is the way you do.

Note, however, that with (IConvertible) types like these built-in numeric types, you can also use the Convert class, so:

return Convert.ToSingle(result);

It looks more pretty, but I don't think it's faster. It will probably do the same kind of type checking.

If the parser gives only numeric types, and if for some reason you insist on boxing these value types, you might as well box them to IConvertible, so that involves changing the return type like this:

private IConvertible parser(string expr) {...}

Then your code could go so:

IConvertible result = parser(expr);  // it's some number boxed in an IConvertible reference type
return result.ToSingle(null);  // instance method in IConvertible
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top