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?
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;
}
}
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
}
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;
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
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;
}
Related
So I want to make a function that when it is called it subtracts a variable from another variable sorry if I am not being clear i want to do something like this
int TreeHealth = 100;
int HitValue = 25;
Hit();
{
TreeHealth - HitValue;
}
I tried doing that but it didn't work, so pls help.
You can make a function to return your value, for sample:
int Hit()
{
return TreeHealth - HitValue;
}
In this case, int is the result of the Hit function.
Using arguments
You also can pass arguments if you need:
int Hit(int tellHealth, int hitValue)
{
return tellHealth - hitValue;
}
The int type is the classic integer number, but there are other types you can work with math operations, such as decimal, double, short, long, etc.
public int Hit()
{
return TreeHealth - HitValue;
}
I want a pass several variables to a function to and set them to something else instead of reading from them. I am planning to use this in a scenario where i can create a object, and add it to a execution queue. Would a pointer be right for this?
I am aware my question has a poor explanation, but I don't know a better way to explain it.
It sounds like you probably want a ref or out parameter. For example:
public static void SetVariables(out int x, ref int y)
{
// Can't *read* from x at all before it's set
x = 10;
// Can read and write y
y++;
}
public static void Foo()
{
int setOnly;
int increment = 5;
SetVariables(out setOnly, ref increment);
Console.WriteLine("{0} {1}", setOnly, increment); // 10 6
}
See my parameter passing article for more information.
Are these variables reference types or value types? If they are reference types then you can pass them into your function as per normal and then mutate its properties from there. If they are value types then you must use the ref keyboard.
First of all, I apologize if this has been asked a thousand times. I read my C# book, I googled it, but I can't seem to find the answer I am looking for, or I am missing the point big time.
I am very confused with the whole boxing/unboxing issue. Say I have fields of different classes, all returning typed variables (e.g. 'double') and I would like to have a variable point to any of these fields. In plain old C I would do something like:
double * newVar;
newVar = &oldVar;
newVar = &anotherVar;
...
I have a timer calls a function and passes the value of the referenced variable:
ChartPlotData(*newVar);
The reason why I am looking for a pointer is because newVar changes at runtime, linked to an Event:
public void checkbox_Clicked(object sender ...)
if (sender == checkbox1) value = &object1.field1;
if (sender == checkbox2) value = &object2.field1;
How can this be done in C#?
EDIT1: Explained purpose of referencing.
EDIT2: Made some incorrect statements, deleted them and shortened the question.
You could have a click event, as suggested in your edit, and then use a delegate to select the data to be passed to the control. I'm not sure if that'll meet your performance requirements though.
ChartPlotData(valueSelector());
// ...
Func<double> valueSelector;
protected void Checkbox_Click(object sender /* ... */)
{
if (sender == checkbox1) valueSelector = () => object1.field1;
if (sender == checkbox2) valueSelector = () => object2.field1;
// ...
}
(If you preferred, and if you're able to, you could overload your ChartPlotData method to accept a Func<double> rather than a plain double, and then invoke the selector delegate lazily inside the method rather than at the call site.)
Simple types and structs are of value type in C#. You can't do anything about it unless as you mentioned you use unsafe modifier. Having said that, your options are limited.
Use object instead of primitive types.
Use arrays of size 1.
Custom generic proxy class encapsulating either of above.
???
You can refer to an existing value type using the ref keyword.
public static void ModifyNumber(ref int i)
{
i += 1;
}
static void Main(string[] args)
{
int num = 4;
ModifyNumber(ref num);
ModifyNumber(ref num);
ModifyNumber(ref num);
ModifyNumber(ref num);
// num now equals 8
}
I am not sure why you need address of the variable. Double is value type and is stored in stack. To pass it by refference into the method just use C# ref keyword.
From cases you have mentioned I personally would prefer something like this:
class Program
{
public class Refferenced<T> where T : struct
{
public T Value { get; set; }
}
static void Main(string[] args)
{
Refferenced<double> x = new Refferenced<double>();
Refferenced<double> y = new Refferenced<double>();
y.Value = 2;
x = y;
x.Value = 5;
Console.WriteLine(x.Value);
Console.WriteLine(y.Value);
y.Value = 7;
Console.WriteLine(x.Value);
Console.WriteLine(y.Value);
Console.ReadKey();
}
It is similar to C# NullAble types.
In C++ I can do this:
int flag=0,int1=0,int2=1;
int &iRef = (flag==0?int1:int2);
iRef +=1;
with the effect that int1 gets incremented.
I have to modify some older c# code and it would be really helpful if I could do something similar, but I'm thinking ... maybe not. Anybody?
UPDATE: The feature discussed below was finally added in C# 7.
The feature you want - to make managed local variable aliases is not supported in C#. You can do it with formal parameters - you can make a formal parameter that is an alias of any variable - but you cannot make a local which is an alias of any variable.
However, there is no technical difficulty stopping us from doing so; the CLR type system supports "ref local variables". (It also supports ref return types but does not support ref fields.)
A few years back I actually wrote a prototype version of C# which supported ref locals and ref return types, and it worked very nicely, so we have empirical evidence that we can do so successfully. However, it is highly unlikely that this feature will be added to C# any time soon, if ever. See http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/ for details.
I note that if I were you, I would avoid this in any language. Writing programs in which two variables share the same storage makes for code that is hard to read, hard to understand, hard to modify and hard to maintain.
See also the related question: Why doesn't C# support the return of references?
You can do it - or at least something very similar to what you want - but it's probably best to find another approach. For example, you can wrap the integers inside a simple reference type.
If you still want to do it, see the Ref<T> class posted by Eric Lippert here:
sealed class Ref<T>
{
private readonly Func<T> getter;
private readonly Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value { get { return getter(); } set { setter(value); } }
}
public class Program
{
public static void Main()
{
int flag=0,int1=0,int2=1;
Ref<int> iRef = (flag == 0 ?
new Ref<int>(() => int1, z => { int1 = z; }) :
new Ref<int>(() => int2, z => { int2 = z; }));
iRef.Value += 1;
Console.WriteLine(int1);
}
}
Output:
1
If all you need is to modify a value type within a function, then pass the parameter with the ref keyword.
int i = 0;
void increment(ref int integer)
{
integer++;
}
increment(ref i);
Yes you can do that with C# 7.0. It has support for returning references and storing references. See my answer here.
Fraid not. You could do it with unsafe code and pointers like so:
int flag=0,int1=0,int2=1;
unsafe
{
int *iRef = (flag==0? &int1:&int2);
*iRef +=1;
}
(not saying that's a good idea or anything :))
There is no direct equivelent in C#. There are a couple of options -
You can use unsafe code and pointers as suggested by dkackman.
Another alternative is to use a reference type (class) which holds the value. For exmaple:
// Using something like
public class Wrapped<T> {
public Wrapped(T initial) {
this.Value = initial;
}
public T Value { get; set; }
}
// You can do:
bool flag=false;
var int1 = new Wrapped<int>(0);
var int2 = new Wrapped<int>(1);
Wrapped<int> iRef = flag ? int2 : int1;
iRef.Value = iRef.Value + 1;
Since you're working with references to a class, the assignment to iRef copies the reference, and the above works...
You could use an Action delegate like this:
int flag = 0, int1 = 0, int2 = 0;
Action increment = flag == 0 ? (Action) (() => ++int1) : () => ++int2;
increment();
In C++, I have a function:
void MyFunction(int p)
{
p=5;
}
Assume, I have:
int x = 10;
MyFunction(x); // x = 10
MyFunction(&x); // x = 5
How to archieve this in C# with condition: I create only one MyFunction.
Your C++ function doesn't work the way you think it does. In fact, your code will not compile.
In C#, you would use the ref or out keywords:
void MyFunction1(out int p)
{
p = 5;
}
void MyFunction2(ref int p)
{
p = p + 1;
}
int x;
MyFunction1(out x); // x == 5
MyFunction2(ref x); // x == 6
In C# you would need to declare the method with a ref parameter, like this:
void MyFunction(ref int p)
{
p=5;
}
If you then call it as MyFunction(ref x) the value of x in the caller will be modified. If you don't want it to be modified simply copy it to a dummy variable. You could create an overload of MyFunction that does this internally:
void MyFunction(int p)
{
MyFunction(ref p);
}
It would technically not be "one function", as you want, but the code wouldn't be duplicated and to any human reading your code it would appear as one - but to the compiler it's two. You would call them like this:
int x = 10;
MyFunction(x); // x = 10
MyFunction(ref x); // x = 5
C# does not have the equivalent functionality. If you declare the method to have a ref parameter, then you must also specify that the parameter is ref type when you call the method.
You need to pass the parameter as reference. If you don't specify it, it automatically creates a copy to work inside the parameter instead of using the same reference.
How to do that? Just specify with the 'ref' word in method declaration:
void MyFunction(ref int p)
{
p=5;
}
int x = 10;
MyFunction(ref x); // x = 5
The point is that a lot of people think that Reference types are passed by reference and Value types are passed By Value. This is the case from a user's perspective, internally both Reference and Value types are passed By Value only.
When a Reference type is passed as a parameter, its value, which is a reference to the actual object is passed. In case of Value types, their value is the value itself (e.g. 5).
StringBuilder sb = new StringBuilder();
SetNull(sb);
SetNull(ref sb);
if SetNull(...) sets the parameter to null, then the second call will set the passed in StringBuilder parameter to null.