Out argument of function call should maintain initialized value - c#

I have defined a function where one of the parameters is out. Here, when the function call is made, I pass either a an initialized or an uninitialized argument.
Now, in the case of an initialized argument, how do I make the callee not change the value of the out parameter?
I cant use a ref here because sometimes I do send an uninitialized argument.
Ex:
void fun1()
{
int x = 3;
fun2 (out x);
int y;
fun2(out y);
}
void fun2(out int x)
{
...
}
Here, I dont want the x to lose the value 3 once control goes to fun2.

From out C# - MSDN
Although variables passed as out arguments do not have to be initialized before being passed, the called method is required to assign a value before the method returns.
Since a value must be assigned to the parameter with out, you can't save the value in function. It would be better if you make a copy of the variable before calling the function. like:
int x = 1;
int backupX = x;
fun2(out x);

Maybe I get all wrong, but this sounds like you just want to define a method like this
void caller(){
int x=5;
int y = doSomething(x);
}
int doSomething(int x){
return x+1;
}
or in case you want a null state use:
void caller(){
int? x=5;
int y = doSomething(x);
}
int doSomething(int? x){
if (x == null)
return x;
return x+1;
}

Related

Call function with a parameter from another function

I have a function that repeatedly calls another function.
The second function has a bool parameter that changes the way it behaves, so when I call the first function I want to have a parameter that specifies the way the second function behaves.
void Function1(int n, bool differentBehavior = false)
{
int a = Function2(n, differentBehavior);
int b = Function2(1, differentBehavior);
int c = Function2(2, differentBehavior);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
The code itself is obviously an example (in reality the second function is called over 20 times and for code readability I would love to not have to specify the second parameter every time), but I put it there to explain what I'm currently doing. Is there no better way to achieve this?
You can introduce a local function to capture the second argument like so:
int Function1(int n, bool differentBehavior = false)
{
int func(int n) => Function2(n, differentBehavior);
int a = func(n);
int b = func(1);
int c = func(2);
return a + b + c;
}
This is called "partial function application". See more here:
https://codeblog.jonskeet.uk/2012/01/30/currying-vs-partial-function-application/
While C# doesn't support true function Currying nor first-class partial function application, you can always
use a new locally scoped function (aka a local function) to wrap your Function2 with predefined arguments... which is conceptually almost the same thing as partial application, just without referential-transparency, and awkward delegate types.
Anyway, if you want to pass the outer Function1's differentBehavior argument value to Function2 then you will need to use a closure, which will capture the variable, but this will introduce slight runtime performance complications: as a closure generally means a GC heap allocation and copying function local state from the stack onto the heap and yada yada.
However, if you're only using constant parameter values - or you're okay with using different wrappers for different predefined argument values, then you can use a static local function (requires C# 8.0 or later) which prevents you from unintentionally creating a closure.
For example:
void Function1(int n, bool differentBehavior = false)
{
// Look ma, no closure!
static int PartiallyAppliedFunc2_False(int x) => Function2( x: x, differentBehavior: false );
static int PartiallyAppliedFunc2_True(int x) => Function2( x: x, differentBehavior: true );
int a = PartiallyAppliedFunc2_False(n);
int b = PartiallyAppliedFunc2_False(1);
int c = PartiallyAppliedFunc2_True(2);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
One thing to look at when a lot of parameters are being passed on the stack is whether there is some higher-level state that could be represented by a member variable of the class.
Here's some code for the most basic kind of state machine. This general approach might help solve the problem you're having:
class Program
{
enum Behaviors
{
BehaviorA,
BehaviorB,
BehaviorC,
}
static Behaviors State { get; set; }
static void Main(string[] args)
{
for (State = Behaviors.BehaviorA; State <= Behaviors.BehaviorC; State++)
{
Console.WriteLine($"Function returned { Function1(0)}");
}
int Function1(int n)
{
int a = Function2(n);
int b = Function2(1);
int c = Function2(2);
return a + b + c;
}
int Function2(int x)
{
switch (State)
{
case Behaviors.BehaviorA:
return x * 10;
case Behaviors.BehaviorB:
return x * 20;
case Behaviors.BehaviorC:
return x * 30;
default:
throw new NotImplementedException();
}
}
}
}

What exactly is parameter containing with ref modifier?

I want to ask something about ref modifier.
What I know and understand:
With method that use ref modifier, there will be no copy of data as with passing by value, but parameter will have directly access to argument value. Basically said, all you done in method’s scope will act same as if you would done it with argument (passed variable) in caller’s scope.
and I want to ask what is exactly stored in parameter with ref modifier:
When I pass argument to method with ref modifier, will parameter contain reference to value of argument? or is it something else?
Thank you for your answers
When you have a parameter with the ref attribute, it passes the argument by reference and not value. That means a new copy of the variable is not being made, rather a pointer to the original is being used within your function.
public void Foo()
{
var x = 0;
Bar(x); // x still equals 0
Bar(ref x); // x now equals 1
}
public void Bar(ref int x)
{
x = 1;
}
public void Bar(int x)
{
x = 1;
}
Let's say we have this method:
public void DoSomething(int number)
{
number = 20;
}
And we use it:
var number = 10;
DoSomething(number);
Console.WriteLine("Our number is: {0}", number);
The output would be Our number is: 10. Our number does not become 20.
That's because we're passing by value, so we're basically taking a copy of number before we change it.
However, if we pass by reference instead:
public void DoSomething(ref int number)
{
number = 20;
}
And then use our method:
var number = 10;
DoSomething(ref number);
Console.WriteLine("Our number is: {0}", number);
The output then becomes Our number is: 20

How to typecast single element of List<double> as type 'double' in calculation in C#

Suppose I have an initialized list: List<double> o
I'd like to perform the following:
int offset = 10;
for (int i = 0; i < o.Count; ++i){
o[i] = ApplyRamp(o[i]-offset)
}
where ApplyRamp is defined as:
public static void ApplyRamp(ref double x)
{
if (x < 0) x = 0;
}
But the code won't compile. Why isn't the single element of a List<double>, i.e. o[i], not treated as type double?
There are four problems here:
You have to use ref on the argument as well as the parameter
The expression o[i] - offset is classified as a value rather than a variable, so you can't pass it by reference
Even the expression o[i] would be classified as a value, as it's the result of calling an indexer. If o were a double[] (i.e. an array instead of a list) then o[i] would be classified as a variable.
You're trying to use the result of a void method as the right-hand side of an assignment operator. A void method doesn't have a result.
You could use:
double temp = o[i] - offset;
ApplyRamp(ref temp);
// Do something with temp?
But it's not clear what you'd do with temp afterwards anyway. Are you trying to modify o? If so, where does offset come in? And why would you be assigning to o[i] as well in that case?
Finally, I'd strongly urge you to consider making your ApplyRamp just use a regular by-value parameter and return the result instead. That will make it easier to use in most cases. I rarely see a good use of ref parameters in void methods.
So something like:
public static double ApplyRamp(double x)
{
return x < 0 ? 0 : x;
}
Or just use Math.Max:
public static double ApplyRamp(double x)
{
return Math.Max(x, 0);
}
You can't assign void to any variable, I think you should change signature of your method:
public static double ApplyRamp(double x)
{
if (x < 0) return 0;
return x;
}
Now your method will return double and will assign this value to o[i] element.
void type description
When used as the return type for a method, void specifies that the method doesn't return a value.
And obviously you want to return a value here. Because (as I suppose), you want to adjust x to be non-negative. So I think changing your code to return double is best way.
If you simply want to get a list with the same values, but decreased by offset or equal to 0 for values which are less than offset, you can use LINQ Select.
It will create a new List<double> by applying a calculating function to the every item in your o array, and then will assign this List back to o:
o = o.Select(x => x - offset < 0 ? 0 : x - offset).ToList();
or
o = o.Select(x => Math.Max(x - offset, 0)).ToList();

In a C# public method, what does the `int` indicate apart from the type integer?

In C#, when defining a public method like:
public int myMethod(String someString)
{
//code
}
What does the int indicate apart from the type integer? What confuses me is that the method is using a String as arguments in this case.
It is the return type of the method. In this case a 32-bit signed integer with a range of
-2,147,483,648 .. +2,147,483,647
It corresponds to the .NET type System.Int32. int is just a handy C# alias for it.
You would return a value like this
public int Square(int i)
{
return i * i;
}
And you could call it like this
int sqr = Square(7); // Returns 49
// Or
double d = Math.Sin(Square(3));
If you do not need the return value, you can safely ignore it.
int i;
Int32.TryParse("123", out i); // We ignore the `bool` return value here.
If you have no return value you would use the keyword void in place of the type. void is not a real type.
public void PrintSquare(int i)
{
Console.WriteLine(i * i);
}
And you would call it like this
PrintSquare(7);
The method in your example accepts a string as input parameter and returns an int as result. A practical example would be a method that counts the number of vowels in a string.
public int NumberOfVowels(string s)
{
const string vowels = "aeiouAEIOU";
int n = 0;
for (int i = 0; i < s.Length; i++) {
if (vowels.Contains(s[i])) {
n++;
}
}
return n;
}
It stands for "integer", and it means the method returns an integer number of 32 bits, also known in C# as Int32.
As previously stated, it's what the method returns.
For example:
public string x()
{
return 5;
}
Would error. 5 is definitely not a string!
public int x()
{
return 5;
}
Would be correct; since 5 can be considered an int (Short for integer, which is, basically, just a number which cannot have a decimal point. There's also float, double, long and decimal, which are worth reading about)
There must be no way of it not returning, for example, if you do:
public int x()
{
if (false)
{
return 5;
}
}
It will error because if the expression is false (It is of course) it won't be returning an int, it won't return anything.
If you use the keyword void, it means it does not return anything. Ex:
public void x()
{
someFunction("xyz");
}
It's fine that it doesn't return as it's a void method.
I don't think you're new to programming judging by your reputation, but just in case, when you return something you pass it back from the method, for example:
int x;
public int seven()
{
return 7;
}
x = seven();
x will become the return value of the function seven.
Note that the 'dynamic' type works here:
public dynamic x(int x, int y)
{
if (x == y)
{
return "hello";
}
return 5
}
But if you're new to C# don't get caught up in dynamic typing just yet. :)
It is the type of the return value.
Everyone is correct here but the definition from msdn:
"Int32 is an immutable value type that represents signed integers with values that range from negative 2,147,483,648 (which is represented by the Int32.MinValue constant) through positive 2,147,483,647 (which is represented by the Int32.MaxValue constant. The .NET Framework also includes an unsigned 32-bit integer value type, UInt32, which represents values that range from 0 to 4,294,967,295."
Found here on MSDN: Int32 Structure
I suggest you read the documentation found in the link above. It is extremely useful.

Strange behaviour with incrementing int when using Action<> delegate

Given the code below:
class Sample
{
public static void Run()
{
int i = 1;
Action<int> change = Increment();
for (int x = 0; x < 5; x++ )
{
change(i);
Console.WriteLine("value=" + i.ToString());
}
}
public static Action<int> Increment()
{
return delegate(int i) { i++; };
}
}
I get the answer:
value=1
value=1
value=1
value=1
value=1
value=1
Instead of 1, 2, 3 ... 6.
This is from an article on the net with links to clues but I can't work out why this is. Anyone have any ideas?
Your parameter is being passed by value.
Writing i++ will change the value of i to a different int value (unlike a mutable type).
When you write i++ inside the delegate, you're changing the parameter to be equal to a different int value. However, this does not affect the local variable whose value was copied to the parameter.
To solve this, you need to make a delegate with a ref parameter. ref parameters are passed by reference. Therefore, when you change a ref int parameter to a different int value, you'll also change the local variable or field whose reference was passed as the parameter.
For more information, see here.
Since the Action delegates do not take ref parameters, you'll need to make your own delegate type, like this:
delegate void RefAction<T>(ref T param);
The datatype int is a primitive data type and hence a value-type as opposed to a reference type. This means that when you pass variable i to a function it isn't the actual variable that has been passed but instead a copy of the value. And therefore when the parameter is changed inside the function it is the local copy that has been changed and no the original variable.
If you are certain you want the function to be able to modify the value of the original variable, then you should add the ref keyword to the function parameter signature to tell the compiler that you want to pass the variable as a reference.
public void ChangeOriginal(ref int something)
{ something = something + 1;}
public void ChangeLocalCopy(int something)
{something = something + 1;}
I suggest you read up upon the stack vs the heap (value-type vs reference-type) since it's a very fundamental subject when programming.
the Action returns nothing. Its only incrementing the value passed in - not the reference to the orginal (as Slaks says). You can use a Func to do in this way.
class Sample
{
public static void Run()
{
int i = 1;
Func<int, int> change = Increment();
for (int x = 0; x < 5; x++ )
{
i = change(i);
Console.WriteLine("value=" + i.ToString());
}
}
public static Func<int, int> Increment()
{
return delegate(int i) { return ++i; };
}
}

Categories