views:

185

answers:

5

I need to downcast a long to an int in a method where the long is passed as a ref variable:

public void Foo(ref long l)
{
    // need to consume l as an int
}

How can I easily do this?

+3  A: 

You don't. You can't take your reference and point it to a different type. How would the code calling your method know that it's changed?

If you just want to work with the value as an int, then you could do something like this:

private void Process(ref long l)
{
    int i = (int)l;
    // do whatever
}
mquander
You'll want to set "l = i;" before the method exits if you manipulate i in the method.
Michael Meadows
Sure, assuming you actually want to modify the reference. Only God knows what the original poster wants to do with it.
mquander
True, it's an interesting exercise in the power of ambiguity to see the diversity of answers that accrete from such a terse 9 word question.
Michael Meadows
someone among you guys understood what i was looking for and gave a perfect answer.. so buzz off :)
jyotishka bora
@jyotishka bora: But Jon Skeet has super powers, so that's really not fair.
Michael Myers
[buzzing off], although that's not a very good way to treat people who are trying to help you.
Michael Meadows
A: 

You cannot directly cast this. The best option would be to cast it to a local, then assign it at the end of your method.

void Method(ref long myValue)
{
   int tempValue = (int)myValue;
   // change tempValue
   myValue = tempValue;
}
Reed Copsey
+1  A: 

You're a little light on the details, but if you're talking about this scenario:

public void Something(ref long something)
{
    // code
}

int foo;
Something(ref foo);

try this:

long foo;
Something(ref foo);
int bar = (int) foo;
Michael Meadows
+1  A: 

You can't safely cast a long to an int regardless of whether it's nullable or not as theres a chance it will overflow.

try this

        if (!blah.HasValue)
            blah = long.MaxValue;

        int x = (int)blah.Value;

        Console.WriteLine(x); //Not What you expect
Eoin Campbell
+5  A: 

You can't. However, any value you want to put into a ref int can be put into a ref long anyway - you've just got to worry about the initial value, and what you want to do if it's outside the range of int.

How many places do you need to write to the ref parameter or read it within your code? If it's only in one or two places, you should be okay just to cast appropriately at the right times. Otherwise, you might want to introduce a new method:

public void Foo(ref int x)
{
    // Here's the body I *really* want
}

public void Foo(ref long x)
{
    // But I'm forced to use this signature for whatever
    // reasons. Oh well. This hack isn't an *exact* mimic
    // of ref behaviour, but it's close.

    // TODO: Decide an overflow policy
    int tmp = (int) x;
    Foo(ref tmp);
    x = tmp;
}

The reason I say in the comments that it's not an exact mimic for the behaviour is that normally changes to the original ref parameter are visible even before the method returns, but now they'll only be visible at the very end. Also, if the method throws an exception, the value won't have been changed. The latter could be fixed with try/finally, but that's a bit clunky. In fact, if you want the try/finally behaviour you can do it all in a single method easily:

public void Foo(ref long x)
{
    int y = (int) x;
    try
    {
        // Main body of code
    }
    finally
    {
        x = y;
    }
}
Jon Skeet
I would add that if the OP has control of the method that defines the ref parameter, it should be changed to a return value. I have never seen a situation in managed code where ref variables served any purpose except to make code messy, and induce sloppiness (difficult to trace side-effects).
Michael Meadows
Do you include "out" parameters in that too? I rather like the TryParse etc pattern.
Jon Skeet
I'm torn on out variables. It's essentially a second return value, which reeks of bad design (unless it's for interoperability). On the other hand, the problem with side-effects doesn't exist, so it's hard to argue that it is dangerous. Inconsistent yes, dangerous, no. I wonder if they had it to do again (after generics), if the framework team wouldn't have implemented ParseResult<T> as a return value. It would mean an extra line of code for each parse, but it would fit in with framework design better.
Michael Meadows
As a side note, one of the most interesting extension methods I have seen is: *** public static void IfDecimal(this string toParse, Action<decimal> toExecute) { decimal d; if (decimal.TryParse(toParse, out d)) toExecute(d); } "5.6".IfDecimal(Console.WriteLine); ***
Michael Meadows