Passing a struct via an Action in C# does not compile - c#

I have a code which works and compiles perfectly, where I have an Action defined as:
Action<double, double, double ....> OnBlah;
Now I have more than 16 params, so I want to pass a struct instead, so I defined the action as:
Action<structName> OnBlah;
But I get an error in the C# compiler that says that structName is not initialized. This is weird since:
A. Previously in the code I passed the double parameters for OnBlah from the struct directly.
B. Structs are initialized by definition.
I'm using VS 2010, I'm guessing this is a compiler bug ?
Added reproduction code for the compiler bug:
namespace CompilerBug
{
struct Test
{
public double a;
}
class Program
{
static Action<Test> OnBlah;
static void DoesCompileOk()
{
Test test;
test.a = 5;
OnBlah(test);
}
static void DoesNotCompileOk()
{
Test test;
int b = 0;
if (b == 4)
{
test.a = 5;
}
OnBlah(test);
}
static void Main(string[] args)
{
OnBlah = (t) => { };
}
}
}

This is not a compiler bug. You need to initialize the struct first, like the compiler says. Presumably your error is actually in the code which invokes the delegate since nothing else makes sense.
When you were invoking the delegate with your 16 parameter double version, the double parameters were initialized. If you had not initialized them, then the compiler would have emitted the same error. For example:
private static void actDouble(double d)
{
}
static void Main(string[] args)
{
double d;
Action<double> act = actDouble;
act(d);//error on this line
}
This fails to compile with the following error:
error CS0165: Use of unassigned local variable 'd'
There is nothing special about structs in this regard.
As a general rule, your first guess when you encounter a syntax error should never be that this is a compiler bug. Compiler bugs are exceedingly rare, especially in a compiler as widely used as this one.
Update following the edit to the question which added real code
Test test;
int b = 0;
if (b == 4)
{
test.a = 5;
}
OnBlah(test);
The compiler is not sure that test is fully initialized. It does not do program flow analysis. You can fix the problem by making sure that the compiler knows that the struct is fully initialized.

Action<structName> OnBlah;
can never raise the error you cite; if either of the two types Action or structName can't be resolved, it'll complain - and if the generic type argument isn't suitable it'll complain, but that is expected.
If OnBlah is a field it is automatically initialized to null; if it is a variable it will need to be assigned before use. It could be assigned to null, but if so it will fail at runtime when you try to invoke it (unless you do a null-check). So then we come to invoke; if we assume non-null, you need to supply an argument, i.e.
OnBlah(someValue); // or OnBlah.Invoke(someValue);
here, if someValue has not been defined it will error; it if is not definitely assigned it will error. For definite assignment, fields are assigned; variables are not unless initialized.
In the case of structs, a value is initialized either by using the constructor (or another method that returns the value), or by manually setting every field (which shouldn't be possible, since a: structs should be immutable, and b: fields should be private).

Related

Why cannot I pass the address of a variable to an anonymous function?

unsafe class Program
{
static void Main(string[] args)
{
int x;
Thread t = new Thread(() => { sum(12, 6, &x); }); // can't pass adrees of x
}
static unsafe void sum(int a ,int b,int* p)
{
*p = a + b;
}
}
Throws the error:
Error CS1686: Local 'x' or its members
cannot have their address taken and be used inside an anonymous method
or lambda expression
The issue is the lifetime of the variable vs. the lifetime of the address taken in the lambda in which it's used. The compiler can ensure that the variable itself lives as long as the lambda (because it's stored in a separate hidden class, due to the capturing), but the address itself (which could be copied somewhere else after the fact) may live longer than the variable, and thus would refer to an address that is no longer valid.
Note that this contrasts with variables captured and used as ref or out parameters. For example:
class Program
{
static void Main(string[] args)
{
int x;
Thread t = new Thread(() => { sum(12, 6, out x); });
}
static void sum(int a, int b, out int p)
{
p = a + b;
}
}
The above is allowed, because the captured variable will be moved from the stack to a separate class that holds it, and that class's lifetime can be ensured to be at least as long as the delegate that will use it.
The unsafe throws a monkey wrench into the works. Unlike ref and out, which have semantics that the compiler can enforce and always use safely, pointers can be stored in arbitrary ways, and the compiler has no way to ensure the lifetime of those pointers. So, even if it captures the x variable to a hidden class like it would in other situations, it still can't guarantee that class remains live for at least as long as the address.
Your specific example is theoretically safe, because the address isn't actually stored anywhere and is used immediately by the method that the anonymous methods calls. But the compiler can't guarantee that safety, and so prohibit any taking of the address of the captured variable.
The memory location may have gone out of scope by the time the lambda is executed. Same reason you can't ref or out a parameter in a lambda. Lambda expressions capture the values of referenced variables at initialization time and use the captured values when they execute. Without the warning, you'd capture the address of x, then later when the lambda executes you would overwrite something else.

C# compiler type inference with dynamic function parameters

When I call a function and replace one of the parameters with dynamic, the compiler inferres the function result to be dynamic. I don't understand why this happens.
Example: the inferred type for a is dynamic, so this code compiles, but of course fails at runtime with RuntimeBinderException:
dynamic b = "";
var a = MethodWithoutOverloads("", b);
a.DoesNotExist();
...
public string MethodWithoutOverloads(string a, string b) { ... }
Somebody knows why the type inferred is not the return type of the function?
EDIT: edited to make clear this happens with methods without overloads
You are right in the sense that the compiler could reason out that all String.Format overloads return a string and therefore infer that a must be a string no matter what b really is.
The truth is that the compiler does not do that. It solves the general case, which is good, and because overloads with different return types are valid in C#, it simply assigns the return type as dynamic and lets the runtime figure it out.
Answering your specific question,
public string MethodWithoutOverloads(string a, string b) { ... }
dynamic a = "";
var result = MethodWithoutOverloads(a, a); // result is dynamic.
Lets imagine the compiler decides that result is string and you publish to the wild west your library. Then, later on, you decide to add an overload with the following signature:
public int MethodWithoutOverloads(int a, int b) { ... }
Now, what should the type of result be? And, what happens to existing code that relied on result being strongly typed to string?
string result = MethodWithoutOverloads(someDynamicVariable, someOtherDynamicVariable);
The semantics change completely; before a consumer had a safe strongly typed variable, now he suddenly has a potentially unsafe implicit cast that can blow up in runtime.
Because the compiler doesn't know which method is going to be invoked at run time.
For example, you may have the two methods:
int MyMethod(int a)
{
return 5;
}
double MyMethod(string a)
{
return 6.0;
}
And you write the following code:
dynamic myThing = 5;
var myResult = MyMethod(myThing);
Considering we've explicitly said myThing is dynamic, and this its type is to be determined at runtime, we have no idea which method will be invoked (if any). Thus, we don't know the return type, either.

Why does c# compiler allow incorrect match of return value type and variable type?

Consider the following code:
static void Main()
{
dynamic a = 1;
int b = OneMethod(a);
}
private static string OneMethod(int number)
{
return "";
}
Please notice that type of b and return type of OneMethod does not match. Nevertheless it builds and throws the exception at runtime. My question is that why does the compiler let this? Or what is the philosophy behind this?
The reason behind this may be Compiler does not know which OneMethod would be called, because a is dynamic. But why it cannot see that there is only one OneMethod. There will surely be an exception at runtime.
Any expression that has an operand of type dynamic will have a type of dynamic itself.
Thus your expression OneMethod(a) returns an object that's typed dynamically
so the first part of your code is equivalent to
static void Main()
{
dynamic a = 1;
dynamic temp = OneMethod(a);
int b = temp;
}
one way of argue why this is sensible even in your case depends on whether or not you think the compiler should change behavior for that particular line depending when you add the below method
private static T OneMethod<T>(T number)
Now the compiler won't know the type returned until runtime. It won't even know which method is called. The generic or the non generic. Wouldn't you be surprised if it in the first case marked the assignment as a compile error and then by adding a completely different method it got moved to a runtime error?

what is use of out parameter in c#

Can you please tell me what is the exact use of out parameter?
Related Question:
What is the difference between ref and out? (C#)
The best example of a good use of an out parameter are in the TryParse methods.
int result =-1;
if (!Int32.TryParse(SomeString, out result){
// log bad input
}
return result;
Using TryParse instead of ParseInt removes the need to handle exceptions and makes the code much more elegant.
The out parameter essentially allows for more than one return values from a method.
The out method parameter keyword on a
method parameter causes a method to
refer to the same variable that was
passed into the method. Any changes
made to the parameter in the method
will be reflected in that variable
when control passes back to the
calling method.
Declaring an out method is useful when
you want a method to return multiple
values. A method that uses an out
parameter can still return a value. A
method can have more than one out
parameter.
To use an out parameter, the argument
must explicitly be passed to the
method as an out argument. The value
of an out argument will not be passed
to the out parameter.
A variable passed as an out argument
need not be initialized. However, the
out parameter must be assigned a value
before the method returns.
An Example:
using System;
public class MyClass
{
public static int TestOut(out char i)
{
i = 'b';
return -1;
}
public static void Main()
{
char i; // variable need not be initialized
Console.WriteLine(TestOut(out i));
Console.WriteLine(i);
}
}
http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
Out parameters are output only parameters meaning they can only passback a value from a function.We create a "out" parameter by preceding the parameter data type with the out modifier. When ever a "out" parameter is passed only an unassigned reference is passed to the function.
using System;
class ParameterTest
{
static void Mymethod(out int Param1)
{
Param1=100;
}
static void Main()
{
int Myvalue=5;
MyMethod(Myvalue);
Console.WriteLine(out Myvalue);
}
}
Output of the above program would be 100 since the value of the "out" parameter is passed back to the calling part. Note
The modifier "out" should precede the parameter being passed even in the calling part. "out" parameters cannot be used within the function before assigning a value to it. A value should be assigned to the "out" parameter before the method returns.
Besides allowing you to have multiple return values, another use is to reduce overhead when copying a large value type to a method. When you pass something to a method, a copy of the value of that something is made. If it's a reference type (string for example) then a copy of the reference (the value of a reference type) is made. However, when you copy a value type (a struct like int or double) a copy of the entire thing is made (the value of a value type is the thing itself). Now, a reference is 4 bytes (on 32-bit applications) and an int is 4 bytes, so the copying is not a problem. However, it's possible to have very large value types and while that's not recommended, it might be needed sometimes. And when you have a value type of say, 64 bytes, the cost of copying it to methods is prohibitive (especially when you use such a large struct for performance reasons in the first place). When you use out, no copy of the object is made, you simply refer to the same thing.
public struct BigStruct
{
public int A, B, C, D, E, F, G, H, J, J, K, L, M, N, O, P;
}
SomeMethod(instanceOfBigStruct); // A copy is made of this 64-byte struct.
SomeOtherMethod(out instanceOfBigStruct); // No copy is made
A second use directly in line with this is that, because you don't make a copy of the struct, but refer to the same thing in the method as you do outside of the method, any changes made to the object inside the method, are persisted outside the method. This is already the case in a reference type, but not in value types.
Some examples:
public void ReferenceExample(SomeReferenceType s)
{
s.SomeProperty = "a string"; // The change is persisted to outside of the method
}
public void ValueTypeExample(BigStruct b)
{
b.A = 5; // Has no effect on the original BigStruct that you passed into the method, because b is a copy!
}
public void ValueTypeExampleOut(out BigStruct b)
{
b = new BigStruct();
b.A = 5; // Works, because you refer to the same thing here
}
Now, you may have noticed that inside ValueTypeExampleOut I made a new instance of BigStruct. That is because, if you use out, you must assign the variable to something before you exit the method.
There is however, another keyword, ref which is identical except that you are not forced to assign it within the method. However, that also means you can't pass in an unassigned variable, which would make that nice Try.. pattern not compile when used with ref.
int a;
if(TrySomething(out a)) {}
That works because TrySomething is forced to assign something to a.
int a;
if(TrySomething(ref a)) {}
This won't work because a is unassigned (just declared) and ref requires that you only use it with an assigned variable.
This works because a is assigned:
int a = 0;
if(TrySomething(ref a)) {}
However, in both cases (ref and out) any changes made to a within the TrySomething method are persisted to a.
As I already said, changes made to a reference type are persisted outside the method in which you make them, because through the reference, you refer to the same thing.
However, this doesn't do anything:
public void Example(SomeReferenceType s)
{
s = null;
}
Here, you just set the copy of a reference to s to null, which only exists within the scope of the method. It has zero effect on whatever you passed into the method.
If you want to do this, for whatever reason, use this:
public void Example1(ref SomeReferenceType s)
{
s = null; // Sets whatever you passed into the method to null
}
I think this covers all use-cases of out and ref.
from http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
One way to think of out parameters is that they are like additional return values of a method. They are very convenient when a method returns more than one value, in this example firstName and lastName. Out parameters can be abused however. As a matter of good programming style if you find yourself writing a method with many out parameters then you should think about refactoring your code. One possible solution is to package all the return values into a single struct.
In contrast ref parameters are considered initially assigned by the callee. As such, the callee is not required to assign to the ref parameter before use. Ref parameters are passed both into and out of a method.
The typical use case is a method that needs to return more than one thing, so it can't just use the return value. Commonly, the return value is used for a success flag while the out parameter(s) sets values when the method is successful.
The classic example is:
public bool TryGet(
string key,
out string value
)
If it returns true, then value is set. Otherwise, it's not. This lets you write code such as:
string value;
if (!lookupDictionary.TryGet("some key", out value))
value = "default";
Note that this doesn't require you to call Contains before using an indexer, which makes it faster and cleaner. I should also add that, unlike the very similar ref modifier, the compiler won't complain if the out parameter was never initialized.
In simple words pass any variable to the function by reference so that any changes made to that variable in side that function will be persistent when function returns from execution.
Jon Skeet describes the different ways of passing parameters in great detail in this article. In short, an out parameter is a parameter that is passed uninitialized to a method. That method is then required to initialize the parameter before any possible return.
generally we cannot get the variables inside a function if we don't get by a return value.
but use keyword "out" we can change it value by a function.

Does casting an Object in C# always return a Reference to the initial object

I'm currently doing a project in C# working with windows forms. During the course of it, I did the following
void HideButtons(object sender, EventArgs e)
{
Button hider = ((Button)sender);
foreach(Button tohide in hider.Parent.Controls)
tohide.Hide();
hider.Show();
hider.Text = "UnHide";
hider.Click -= new EventHandler(HideButtons);
hider.Click += new EventHandler(ShowButtons);
}
The purpose of this code is to have a button which hides all the other buttons in the container it's in except itself, and then turn into an Unhide button which does the same thing in reverse.
Now, that's all well and good, except, as I compile this, I realize to myself I've hit a problem. hider is its unique object, being the return from ((Button)sender). It's not necessarily the reference to sender, and this code will probably do nothing.
But low and behold, it works exactly like I wanted it to and initially thought it would. Which got me to wondering, does a cast always return a reference to the original object? If not, how do I guarantee that (button)sender = sender?
I know that's not the case for doubles/ints, as
public static int Main()
{
int a;
double b;
b = 10.5;
a = (int)b;
a++;
return 0;
}
ends up with a being 11, and b being 10.5 But that may be due to doubles/ints being structs. This behavior worries me, and it'd be nice to know that it will always return a reference so I can put my worrysome mind to rest.
For reference types. if the cast is just up or down the inheritance hierarchy, then yes. This is a reference conversion. From the C# 3.0 language spec, section 6.2.4:
Reference conversions, implicit or
explicit, never change the referential
identity of the object being
converted. In other words, while a
reference conversion may change the
type of the reference, it never
changes the type or value of the
object being referred to.
This is the case you're using in your WinForms code.
However, in other (still reference type) cases it may invoke a user-defined conversion. For example:
using System;
class Foo
{
}
class Bar
{
public static explicit operator Bar(Foo f)
{
return new Bar();
}
}
class Test
{
static void Main()
{
Foo f = new Foo();
Bar b = (Bar) f;
Console.WriteLine(object.ReferenceEquals(f, b)); // Prints False
}
}
User-defined conversions like this are relatively rare.
For value types, there are boxing and unboxing conversions, along with other conversions (e.g. between int and double).
For reference types casted through the inheritance hierarchy, it'll always reference the same instance. However, for value types, casts might involve boxing and unboxing which will copy stuff. Other than that, casts are not just in the inheritance hierarchy. You can declare your own cast operator which has the characteristics of a method. It can return whatever object it likes.

Categories

Resources