I was recently reading an answer about CS1628, "Cannot use ref or out parameter 'parameter' inside an anonymous method, lambda expression, or query expression".
The answer stated a way around this is to implement "ref parameters as boxes" in the CLR.
C# compiler error CS1628 with VS2010/C#4
I am unsure what this means and seem to be unable to find any references to it in google.
Can anyone please explain this to me as its way over my head?
You can declare a "box" class:
class Box<T> { public T Value; }
Pass an instance of that class to the method that you cannot use ref with. The method can reach into the object and mutate Value. The caller can later extract Value.
This works (in constrast to ref) because Box is allocated on the heap and has "infinite" lifetime. ref can only refer to locations with more restricted lifetime.
Related
I'm learning C# with Yellow Book. In the chapter 3.1.9, when describing differences between passing parameter values as ref vs out, it says the following:
When you pass a parameter as a reference you are giving the method complete control of it. Sometimes you don't want this. Instead you want to just allow the method to change the variable.
If I am the one coding the method, i.e. its behavior, how am I giving it complete control of it?
It doesn't mean it is less secure, it just means the method "has control over your variable" that you are passing as parameter for "processing". It can potentially return a completely new object and not the one you "provided". More can be found here:
When used in a method's parameter list, the ref keyword indicates that an argument is passed by reference, not by value. The ref keyword makes the formal parameter an alias for the argument, which must be a variable. In other words, any operation on the parameter is made on the argument.
For example, suppose the caller passes a local variable. The called method can then replace the object to which the ref parameter refers. In that case, the caller's local variable or the array element refers to the new object when the method returns.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Read-only (“const”-like) function parameters of C#
Why is there no const member method in C# and const parameter?
Having programmed in C++ in the past, I recall we could make a constant reference/pointer parameter in a method.
If my memory is correct, the below means, that the method cannot alter the reference and the reference itself is a constant reference.
C++ example
void DisplayData(const string &value) const
{
std::count << value << endl;
}
Is there an equivalent in C# for methods in a class?
The reason why I'm asking is, I'm trying to pass a object by reference (for speed) and at the same time don't want anyone to alter it.
Update 16/09/2020
There now appears to be the in parameter modifier that exhibits this behaviour (in essence, a ref readonly). A brief search on when you would ever use this yields the following answer:
Why would one ever use the "in" parameter modifier in C#?
Original Answer
There is no equivalent for C# and it has been asked many, many, many, many times before.
If you don't want anyone to alter the "reference", or perhaps you mean the content of the object, make sure the class doesn't expose any public setters or methods of mutating the class. If you cannot change the class, have it implement an interface that only publicly exposes the members in a read-only fashion and pass the interface reference instead.
If you mean you want to stop the method from changing the reference, then by default if you pass it "by reference", you are actually passing the reference by value. Any attempt from the method to change what the reference points to will only affect the local method copy, not the caller's copy. This can be changed by using the ref keyword on a reference type, at which point the method can point the reference at a new underlying object and it will affect the caller.
For value types (int, double, byte, char,...,struct) the arguments come in as values and therefore are guaranteed not to affect that calling module.
For string type, although it is a reference type, it is immutable by the CLR, such that nothing you do inside the procedure can affect the original string.
For other reference types (class) there is no way to guarantee changes in the class from the method.
I have a method that takes an anonymous function parameter. This function's parameter is provided by a local variable.
public void DoSomething<T>(Action<T> method) where T : new()
{
T instance = new T();
method.Invoke(instance);
}
I want to prevent creating a closure. Local variable should go out of scope when DoSomething<T> is finished. Is there a way to constrain it at compile time?
Here's the situation I want to avoid:
Foo capturedInstance = null;
DoSomething<Foo>(item => capturedInstance = item);
capturedInstance.Call();
Unfortunately*, that's not possible. You have little to no control over what a method does with its arguments. It would be possible to work around if you weren't using generic types, but you are, so just don't worry about that kind of situation. (I hope you don't have to.)
* Actually, I consider it "fortunately". This isn't C++ we're talking about here.
If T were a struct, it would be possible for code which held a field of type T or an array of type T[] to pass the field or an array element as a ref parameter to an outside method; that method would be able to operate directly and efficiently on that field or array slot without having to make temporary copies of the struct, but once the method returned the type holding the field or array could be confident that outside code could no longer access that slot. Outside could have made a copy of the field or element's contents, of course, but it won't be able to change the original unless or until the type holding the struct again exposes it to outside code.
Unfortunately, if the T is a mutable class, exposing a reference will allow outside code to promiscuously copy and pass around that reference forevermore. For that reason, mutable classes are much worse data holders than mutable structs. If one wants to allow outside code to make use of a class without exposing a direct reference, it's necessary to create a wrapper class and interface. Unfortunately, there's no way of doing this without either using a truly horrible amount of duplicated code, or else using Reflection to generate wrappers at run-time.
I think your code already does what you want.
The delegate representing the lambda item => capturedInstance = item is passed only to DoSomething<Foo>, and that reference is not handed out to anybody else. So, the delegate would go out of scope when the containing method finishes. And so will the local variable that is captured by the lambda expression.
Only if you are passing around a reference to the delegate, you will not get the behavior you want.
A MS help page about the difference between pass-by-value and pass-by-reference seems quite clear to me:
http://msdn.microsoft.com/en-us/library/8b0bdca4.aspx
However, a user comment at the end has confused me somewhat. It says (among other things) this:
if you don‘t use the ref or out keywords, then arguments to methods
are passed by value.
The comment seems quite wrong to me. Is it?
(I posted part of the comment out of context: Here's the full comment:)
The text says: "... but when a class instance is passed, a reference
is passed. ..." This is incorrect, as you can see in:
C# Language specification Version 4.0 (a Microsoft free download)
5.1.4 Value parameters A parameter declared without a ref or out
modifier is a value parameter.
So, in the example above, the class instance is passed by value, and
not by reference.
It is the full comment which is really confusing me... The class instance is passed by value and not by reference? Does that not imply that the instance bytes are pushed onto the stack?
The comment is true. Without ref or out, the variable is passed by value. However, with objects, what you are passing by value is a reference.
The only time you would want to pass an object-reference by reference is if you are assigning a new object to the parameter within the method and you want that reassignment to affect the caller's copy of the reference.
You aren't ever really passing an object around. Instead you are passing around references to an object. With that in mind, this byval/byref business applies to the object-reference, not the object itself.
Jon Skeet has a great post about this topic.
The complete comment is misleading. The object's reference is passed by value.
The comment is completely correct. The confusion here is that value types and reference types are pretty much unrelated to passing an argument by value or by reference.
When you pass a value type as a non-ref parameter, you pass its value. That's clear enough. For a reference type, though, you are still only passing a value: You are passing the value of the reference itself.
If the parameter is ref/out, though, then you are actually saying that the parameter is an alias for the variable that is actually being passed in. In that case, it doesn't matter if it's a value type or a reference type; a reference to the variable is being passed, not just a value.
My brain had a segfault this morning trying to understand exactly how and when C# can work out the type of an object from a reference to that object. Consider the following highly unoriginal example code:
class Foo { public virtual void Baz() { } }
class Bar : Foo { }
class Program {
static void Main() {
Foo f = new Bar();
f.Baz();
}
}
The type of the reference there is Foo, but the object instance actually created is a Bar. That Bar instance has some overhead, i.e. a Sync Block index, and a reference to a MethodTable, presumably Bar's MethodTable. If you look at the Bar object on the heap, the only clue to its type is the MethodTable reference, which would suggest that it's a Bar.
Onto the question then. Is there any way for C# to know from the actual object graph that 'f' is a Foo, and if so, how? Does the reference 'f' contain type information itself? When I call f.Baz(), am I right in thinking that the dispatch occurs via Bar's MethodTable anyway? Is it simply that case that the C# compiler uses flow analysis to work out what's going on and prevent any illegal operations? Does the CLR actually not care about the type declaration of Foo by the time it's been translated into IL?
Apologies if that's a long-winded and poorly-phrased question - let me know if any clarification is required!
TL;DR - How does a polymorphic reference in the CLR work? How is any discrepancy between the actual vs declared class type persisted, and could you tell what the original declaration was from the resultant IL?
You’re thinking way too complicated.
Does the reference 'f' contain type information itself?
No. It doesn’t have to. It is simply an address to the beginning of the Bar object’s memory that was constructed earlier. That object contains a virtual method table (and possibly a reference to its associated Type object1, but that’s irrelevant here).
When I call f.Baz(), am I right in thinking that the dispatch occurs via Bar's MethodTable anyway?
Yes.
Is it simply that case that the C# compiler uses flow analysis to work out what's going on and prevent any illegal operations?
Flow analysis is complex and completely unnecessary here. The compiler allows exactly those operations that are allowed for the declaration type of f – which is Foo. The compiler doesn’t care about the actual (= dynamic) type of f at all.
could you tell what the original declaration was from the resultant IL?
Depends. An object doesn’t have a static type so “telling its static type at runtime” is meaningless. Declarations, on the other hand, differ. If the variable is a formal parameter of a method then sure, you can (at runtime) use reflection to determine the declaration type of the method’s parameter.
For local variables, once again this operation is meaningless. On the other hand, the IL does store this information (as metadata?) via .locals so the code can theoretically be reverse engineered (Cecil and Reflector do this) to get the static type of variables.
1 I’m guessing here but this is actually improbable. If each object held its own reference to an associated Type object, that would mean an additional overhead of a pointer. Additionally, this reference is entirely unnecessary, since the object can simply call GetType on itself to get its type. GetType does only need to be implemented once for each class (kind of a static method, really) and is dispatched via the usual virtual function table. Thus only one reference to a Type is required per class, as opposed to per object.
Is there any way for C# to know from the actual object graph that 'f' is a Foo
That is statically known to the compiler
Does the reference 'f' contain type information itself?
Interesting, it must be contained in the IL somehow.
When I call f.Baz(), am I right in thinking that the dispatch occurs via Bar's MethodTable anyway?
Yes. And that is found through the instance that f points to.