I have a doubt in scope of varibles inside anonymous functions in C#.
Consider the program below:
delegate void OtherDel(int x);
public static void Main()
{
OtherDel del2;
{
int y = 4;
del2 = delegate
{
Console.WriteLine("{0}", y);//Is y out of scope
};
}
del2();
}
My VS2008 IDE gives the following errors:
[Practice is a class inside namespace Practice]
1.error CS1643: Not all code paths return a value in anonymous method of type 'Practice.Practice.OtherDel'
2.error CS1593: Delegate 'OtherDel' does not take '0' arguments.
It is told in a book: Illustrated C# 2008(Page 373) that the int variable y is inside the scope of del2 definition.
Then why these errors.
Two problem;
you aren't passing anything into your del2() invoke, but it (OtherDel) takes an integer that you don't use - you still need to supply it, though (anonymous methods silently let you not declare the params if you don't use them - they still exist, though - your method is essentially the same as del2 = delegate(int notUsed) {...})
the delegate (OtherDel) must return an int - your method doesn't
The scoping is fine.
The error has nothing to do with scopes. Your delegate must return an integer value and take an integer value as parameter:
del2 = someInt =>
{
Console.WriteLine("{0}", y);
return 17;
};
int result = del2(5);
So your code might look like this:
delegate int OtherDel(int x);
public static void Main()
{
int y = 4;
OtherDel del = x =>
{
Console.WriteLine("{0}", x);
return x;
};
int result = del(y);
}
Related
I have been making an effort on C# methods. There are three ways that parameters can be passed to a C# methods.
Value parameters : This method copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument.
Reference parameters : This method copies the reference to the memory location of an argument into the formal parameter. This means that changes made to the parameter affect the argument.
Output parameters : This method helps in returning more than one value.
I understood above types of passing parameters with below sample codes.
using System;
namespace PassingParameterByReference
{
class MethodWithReferenceParameters
{
public void swap(ref int x)
{
int temp = 5;
x = temp;
}
static void Main(string[] args)
{
MethodWithReferenceParameters n = new MethodWithReferenceParameters();
/* local variable definition */
int a = 100;
Console.WriteLine("Before swap, value of a : {0}", a);
/* calling a function to swap the value*/
n.swap(ref a);
Console.WriteLine("After swap, value of a : {0}", a);
Console.ReadLine();
}
}
}
When the above code is compiled and executed, it produces the following result:
Before swap, value of a : 100
After swap, value of a : 5
With this codes i could understand to pass parameters to methods by reference. And then i examine below code to understand passing parameters to methods by output.
using System;
namespace PassingParameterByOutput
{
class MethodWithOutputParameters
{
public void swap(out int x)
{
int temp = 5;
x = temp;
}
static void Main(string[] args)
{
MethodWithOutputParameters n = new MethodWithOutputParameters();
/* local variable definition */
int a = 100;
Console.WriteLine("Before swap, value of a : {0}", a);
/* calling a function to swap the value */
n.swap(out a);
Console.WriteLine("After swap, value of a : {0}", a);
Console.ReadLine();
}
}
}
When the above code is compiled and executed, it produces the following result:
Before swap, value of a : 100
After swap, value of a : 5
These sample codes make same action with different ways. And i can't understand difference between two approaches.( Passing Parameters To Method By Output And By Reference). Two example's output is the same. What is this small difference?
Output parameters dont have to be initialized before the method is called like it is the case for reference parameters.
int someNum;
someMethod(out someNum); //works
someMethod(ref someNum); //gives compilation error
Furthermore, the Output parameter needs to be set or changed within the method, which is not necessary for reference parameters.
With "Reference" parameters, the value needs to be assigned before a method can use it. X and Y in your examples would have needed to have been declared outside the method.
e.g. int x = 100; int y =200;
With "Output" parameters, the value for your parameters don't have to be assigned a value before you can use them. X and Y could have been declared in your example with no starting values assigned to them.
e.g int x; int y;
Reference and Output parameters are very similar.
The only difference is that ref parameters must be initialized.
int myInt = 1;
SomeMethod(ref myInt); //will work
SomeMethod(out myInt); //will work
int myInt;
SomeMethod(ref myInt); //won't work
SomeMethod(out myInt); //will work
The compiler will actually view the ref and out keywords the same. For example if you cannot have overloaded methods where the only difference is the ref and out keywords.
The following methods signatures will be viewed the same by the compiler, so this would not be a valid overload.
private void SomeMethod(ref int Foo){};
private void SomeMethod(out int Foo){};
An output parameter needs to have it's value changed inside the method otherwise the compiler will throw an error.
The reference parameter may or may not have it's reference (reference objects) changed by the method.
Also value types (types defined in structs) cannot be passed by reference.
See this What's the difference between the 'ref' and 'out' keywords?
The difference is that for an out parameter you have to set it before leaving the method. So even if you dont set it to any value before calling the method the compiler knows that it will get a value during the method call.
Appart from technical differences, to have a good readable code, you should use out when the method has more than one output. And use ref when the method just may update the variable
I have a Func in my code that's declared like this:
Func<string, int, bool> Filter { get; set; }
How can I reach the string and the int variables that are parameters of the Func in order to use them in my code?
The parameters only exist when the function is called... and they're only available within the function. So for example:
foo.Filter = (text, length) => text.Length > length;
bool longer = foo.Filter("yes this is long", 5);
Here, the value "yes this is long" is the value of the text parameter while the delegate is executing and likewise the value 5 is the value of the length parameter while it's executing. At other times, it's a meaningless concept.
What are you really trying to achieve? If you could give us more context, we could almost certainly help you better.
You could use an anonymous method:
Filter = (string s, int i) => {
// use s and i here and return a boolean
};
or a standard method:
public bool Foo(string s, int i)
{
// use s and i here and return a boolean
}
and then you could assign the Filter property to this method:
Filter = Foo;
See this sample here - http://www.dotnetperls.com/func
using System;
class Program
{
static void Main()
{
//
// Create a Func instance that has one parameter and one return value.
// ... Parameter is an integer, result value is a string.
//
Func<int, string> func1 = (x) => string.Format("string = {0}", x);
//
// Func instance with two parameters and one result.
// ... Receives bool and int, returns string.
//
Func<bool, int, string> func2 = (b, x) =>
string.Format("string = {0} and {1}", b, x);
//
// Func instance that has no parameters and one result value.
//
Func<double> func3 = () => Math.PI / 2;
//
// Call the Invoke instance method on the anonymous functions.
//
Console.WriteLine(func1.Invoke(5));
Console.WriteLine(func2.Invoke(true, 10));
Console.WriteLine(func3.Invoke());
}
}
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.
Consider this code snippet and try to guess what y1 and y2 evaluate to
static class Extensions
{
public static Func<T> AsDelegate<T>(this T value)
{
return () => value;
}
}
class Program
{
static void Main(string[] args)
{
new Program();
}
Program()
{
double x = Math.PI;
Func<double> ff = x.AsDelegate();
Func<double> fg = () => x;
x = -Math.PI;
double y1 = ff(); // y1 = 3.141..
double y2 = fg(); // y2 = -3.141..
}
}
You might say -Aha- double is a value type and so the value returned by the extension method is a copy of the main x. But when you change the above into delegates of classes the results are still different. Example:
class Foo
{
public double x;
}
Program()
{
Foo foo = new Foo() { x=1.0 };
Func<Foo> ff = foo.AsDelegate();
Func<Foo> fg = () => foo;
foo = new Foo() { x = -1.0 };
double y1 = ff().x; // y1 = 1.0
double y2 = fg().x; // y2 = -1.0
}
So the two functions must return two different instances of the same class. It is interesting to consider that ff() carries with it a reference to local variable foo, but fg() does not and it relies on what is in scope currently.
So what happens when these two delegates are passed on to other parts of the code which do not have visibility to foo instance? Somehow the question of who owns what information (data) is becoming less and less clear when extension methods are combined with delegates.
AsDelegate captures the variable value (the parameter of AsDelegate), while () => x captures the variable x. So if you change the value of x, the lambda expression will return a different value. Changing x doesn't change value though.
See: Outer Variable Trap
In AsDelegate, we are capturing the the argument "value". the value of this argement is taken as a copy of the value of the variable at the time the method is invoked, and never changes - so we see the original object.
The direct lambda captures the variable foo (not the value of the variable - the variable itself) - thus we do see changes to this.
Basically adding a method call changed the thigh being captured.
ff captures (binds) to the value of x at this line:
Func<double> ff = x.AsDelegate();
By contrast, fg binds to the variable x at this line:
Func<double> fg = () => x;
So, when the value of x changes, ff is unafected, but fg changes.
The AsDelegate extension method uses the value of x at the time AsDelegate is called whereas the lambda expression () => x captures the variable x and therefore the value of x is taken at the time the expression is invoked (rather than the value when it was defined).
() => x captures x value. Special class is created by compiler to handle lambdas or anonymous delegates, any variable used in the lambda is captured.
For example if you run following code:
List<Func<int>> list = new List<Func<int>>();
for (int i = 0; i < 5; i++)
{
list.Add(() => i);
}
list.ForEach(function => Console.WriteLine(function()));
you will see that numbers printed are the same.
You need to read about closures in C#. See also Wikipedia.
The first method creates a new delegate to a given function and stores it. It you later overwrite foo, your newly created delegate is not touched.
The second one is a lambda expression which lifts/*captures* its context, that means the foo variable. All changes to variables that has been lifted by lambdas expressions are seen by that lambda expression.
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.