If I had a controller method like so:
public ActionResult<Item> GetItem(RequestHeaderBase headers, RequestObject request)
Can I always assume that the headers object and request object will be instantiated (not null)?
(I would appreciate any links to deeper reading regarding how this works regardless of the answer)
Here is an example of what I mean
Here I call the request: https://localhost:44360/weatherforecast and you can see the input object has been instantiated despite me not providing the query string.
Another example, this time with data from the body:
In both cases, you can see with my debugging, no matter what the objects are instantiated, even if I don't provide any data in the request.
Now I've seen code that checks if this data is null in some of our applications, I believe this code is irrelevant, and so can be removed.
if it is a reference object ( not a value) it will be always instantiated. Each object property will have a default value. This is why any class that are using for action input parameter should have default or parameter less constructor. Otherwise it will cause an exception. Only when object is created, controller trying to assign values to the object properties according to the http request. But be carefull, only the top level will be instantiated. If you have another complicated properties inside of this object, they will be instantied and have a default value according to the type. For example, List will be null (default value), not an empty list. Nullable integer property will ne null, not nullable 0, and so on. But you can assign default values you need in the constructor for example.
even if you change the action signature to this
public ActionResult<Item> GetItem(RequestHeaderBase headers=null, RequestObject request=null)
they still will be instantiated, each property will have a default value according to the type.
Can I always assume that the headers object and request object will be instantiated (not null)?
no, they can be null.
Related
Take the following code for exhibit A:
string sql;
if (!GetQueries.TryGetValue(type.TypeHandle, out sql))
Documentation for Dictionary says that if the Key isn't found, the reference type will be set to null. OK, that's fine.
If the key is found, how is the variable 'sql' filled?
Is the found value for the key cloned?
Is a type of object for the item found created and then the contents of the object copied?
Is this safe?
Or, to set up a place for the outbound object to reside, should the call be set up as exhibit B:
var sql = string.Empty;
if (!GetQueries.TryGetValue(type.TypeHandle, out sql))
Then the variable 'sql' is initialized and a safe place for the object exists.
(My question comes from my aversion of null pointers in my C programming days.)
In my view, it's better not to set it to a value. After all, that value is guaranteed to be replaced by the method call (assuming that doesn't throw an exception) so why bother specifying a value which is pointless? It just misleads the reader into thinking it makes a difference.
An out parameter is special in that the variable you use to provide a value for it doesn't have to be definitely-assigned before the call, but will be definitely-assigned after the call. Any value it has before the call will not be visible to the method.
(Note that ref parameters don't behave that way - they have to be definitely assigned beforehand.)
See my article on C# argument passing for more details on the different parameter modes in C#.
If the key is found, how is the variable 'sql' filled? Is the found value for the key cloned? Is a type of object for the item found created and then the contents of the object copied?
The value of the parameter within the method becomes the value of the variable in the callers code, in the same way as normal assignment. There is no object cloning going on.
If the key is found, how is the variable 'sql' filled?
You can think it like this:
var sql = GetQueries[type.TypeHandle];
Or, to set up a place for the outbound object to reside, should the call be set up as exhibit B:
No actually it doesn't matter. You don't have to initialize sql to a value, since you are passing it as out argument.The function guarantees that it will set the value of it's argument by declaring it as out.
So I was reading Jon Skeet's C# in depth and came across some myths like Reference types are always passed by ref, So I decided to do a little experiment myself.
As you can see in the following code I have a simple Car class with one property which is initialized to 500 when the constructor is called. I also have the NullIt function which assigns null to the parameter value and a SpeedUp method which just changes the Speed property value.
Examining the main method you can see I instantiate a Car object, then I pass the object to the static SpeedUp method and the Speed value changes to 1000 but when I'm passing it to the also static NullIt method the object remains intact. From this the only thing I can assume is that the object is passed by value and the fields / properties are passed by reference. Is this right?
I know that if I pass it using the ref keyword will return null.
class Program
{
static void Main(string[] args)
{
Car c = new Car();
Car.SpeedUP(c);
Car.NullIt(c);
}
class Car
{
public int Speed { get; set; }
public Car() { Speed = 500; }
public static void SpeedUP(Car c)
{
c.Speed = 1000;
}
public static void NullIt(Car c)
{
c = null;
}
}
}
From this the only thing I can assume is that the object is passed by
value and the fields / properties are passed by reference. Is this
right?
Not really. Object's address is passed by value.
So when you do:
Car.SpeedUP(c);
Now your parameter of method SpeedUp and your field c in caller, both point to the same location in memory. Thus changing the property works.
But for your call:
Car.NullIt(c);
Your method parameter c and caller's c both points to same location. But since you assign null to your parameter c , now it is not pointing to any memory location, but the original/caller's c still points to the same memory location.
Consider the following:
When you pass parameter to your method then two references in memory would be pointing to the same address like:
But when you assign null it doesn't change the other reference.
The first reference (in caller) still points to the same location, only the method parameter is now pointing to null.
When you call NullIt() you are passing the value of a reference to your instance of Car. You then change this value to null. However, the original copy of that value remains intact. Exactly the same way passing the value of an int works - you can modify your local copy without affecting the "original".
If you were to change that to NullIt(ref Car c), you would be passing a reference to the reference, and hence setting it to null would set the original value of the reference to null. That last part can be a bit of a mind bender, but it's so rarely necessary (if ever) that you don't need to worry too much about it.
From this the only thing I can assume is that the object is passed by value and the fields / properties are passed by reference. Is this right?
While the observed effect may look like this, the way you describe it has some incorrect implications: The fields/properties are not "passed by reference" in a way that there is a reference to each field/property. It is rather that the reference to the object is passed by value.
That is why by accessing any member of the object, or the object itself, you are accessing the very same instance you passed into the method, not a copy thereof.
However, the variable c itself is a reference, and that reference is passed by value. That is why, in your methods, you cannot change that reference by assigning a new value and expect that the variable c itself now has a new value (in your case null).
It IS a bit confusing, because the word reference is overloaded (has two subtly different meanings).
When describing types as either value types or reference types. it means one thing,
Whether the data for the state of an object of that type is stored on the stack, (which is a section of memory that methods have access to) or whether it is stored on another section of memory called the Heap, and only the address of that section of heap is then stored on the stack, allowing code to only access the object indirectly.
When describing whether parameter values are passed to a method by value or by reference, otoh, it means something different. It means whether the actual value of the parameter is [copied and] passed to the method, or whether the address of the parameter value's memory slot is passed.
So you can actually have four combinations here:
Pass a value type by value - The value is copied and passed to
the method. The method cannot change the source value.
Pass a reference type by value. The address of the reference type
(which is on the Heap) is copied and passed. The method cannot
change the address in the source variable, but it CAN change the
data on the HEAP that the address points to.
Pass a value type by reference. The method gets the address of the
source object, (on the stack) and can change that source value.
Pass a reference type by reference. The method gets the address of
the variable (on the stack) that contains the address of the object
itself (on the Heap). The method can change the data in the source
object, AND CAN ALSO CHANGE WHICH OBJECT (ON THE HEAP) THE SOURCE
VARIABLE POINTS TO)
Quick question :
I am passing a class (reference type) to a method without using the "ref" keyword. Thus, the reference itself to my class is passed by value.
Then, I change the reference of my class (I make the reference point to another instance defined inside my method).
Finally, I return the initial method. However, in this case the returned instances points to the instance of the second class.
public Class Foo(Class A)
{
Class B = new Class();
A = B;
return A;
}
Foo returns a references pointing to B !
I am a little bit confused, since when doing A = B I make the reference of A point to another reference, or A's referenced is passed by value.
EDIT 1
Thanks for the response, but If I take the following example the change is not reflected. Indeed, I am trying to change the references of A but A's references is passed by value so in this case I understand why the change is not reflected..
void Foo(Class A)
{
A = null;
}
Many Thanks.
Basically, when you're passing an object, a reference is passed:
When an object of a reference type is passed to a method, a reference to the object is passed. That is, the method receives not the object itself but an argument that indicates the location of the object. If you change a member of the object by using this reference, the change is reflected in the argument in the calling method, even if you pass the object by value.
You can read more on this MSDN page.
You can read more on the other answers, but do notice that you're returning a class. Usually you'll return a specific object type, and when you won't be so free to do silly things like that. (of course, assuming that B inherits from A, you could create a new B inside the method and return it, which will be valid, but still, it's not making sense).
Another thing you might want to remember is the ref and out.
ref will expect an initialized value, and that value is changed in the method.
out doesn't care what it gets in, but you need to initialize and set it in the method.
Other than that, and the other answers here, either be more specific with your question and code, or have a read at the different links in the answers :)
You are passing a reference - an immutable value - into the method using the mutable variable, more precisely a parameter, A. Then you assign to the mutable variable A a new value, the immutable reference to the newly created object. Finally you are returning the current value of the variable A which at that point is the reference to the new object and no longer the reference to the object you passed into the method.
Essentially you are confusing the variable and the value stored in that variable. At no point did you change any reference, you only exchanged the value, i.e. reference, stored in the variable.
When you pass reference type by value the attempt to reassign the parameter to a different memory location only works inside the method and does not affect the original variable.
Check out Passing reference - type parameters .
So today I discovered that c# passes reference types by value by default. This ran counter to what I thought I understood - reference types are by reference as standard. Oh well.
This led me to think about a method that I had that took an entity object as a parameter, attached to a context, and made some changes to it. The method did not return the object. When calling save changes on my context, the changes made within the method were applied.
I assumed at the time that it worked because I was passing a reference to the object and so could happily alter it without having to return anything to reassign.
So the question is, how does this work? (the code did work as I expected).
Thanks,
Yes, this stuff is tricky. I've found myself not thinking about it for a few months, and then having to think about it for a few seconds to get it straight in my head again. Even though I've understood it for a long time.
Even though the parameter is by value, that just means that a new reference variable is created, but still pointing to the same object. If you make the parameter by reference, then the same pointer would be passed in, which of course points to the same object.
It makes a difference when you mess with the parameter variable. If you set it to null or to some other object, the variable "outside" will not be affected. But if the parameter was passed in by value, then setting the variable to null or another object will alter the reference "outside".
For a value type, whether the parameter is by reference or by value makes a practical difference more often. Changes to the value or to a member (if it's a struct) will not be reflected "outside" if passed by value.
Here's a good explanation with easy examples.
The reference is passed by value (ie the reference is copied not the target object) - it is still a reference to the same object. This is as opposed to passing by reference, where the original reference is passed around.
Hopefully this illustrates the point:
var myObject = new object();
PassByValue(myObject);
Console.WriteLine(myObject == null); // returns false. The fact the method changed its *copy* of the reference to null doesn't affect the caller.
PassByReference(ref myObject);
Console.WriteLine(myObject == null); // returns true. We actually passed in our reference itself, not a copy of the reference; so when the method set it to null, it nulled the reference we held in the caller.
void PassByValue(object obj)
{
obj = null;
}
void PassByReference(ref object obj)
{
obj = null;
}
Reference types in C# are passed by reference. Which means when you pass a reference type only reference is passed to that method not the actual value
When you pass a reference type object to a method you are actually passing a new reference/pointer to that object
Let's understand by example
SomeRefType myRef = new SomRefType();
//above myRef is reference to object of SomRefType type
//pass this reference to a method
SomeMethod(myRef);
SomeMethod(SomeRefType reference)
{
//here reference is a new pointer/reference pointing to same object as myRef
}
I have a method that takes List<Foobar> and Foobar as parameters. Foobar is a regular class with private variables, a constructor, and methods to operate on the data.
I modify both of the instances passed in the method but for some reason I have to pass Foobar with the ref keyword or else the changes do not stick when the method completes. I do not have to do this for the list.
I've noticed this a couple times recently in my programming. Usually when passing an instance of a class to the method, modifying it changes the instance, but sometimes it doesn't and it requires the ref keyword for changes to stick. It seems rather random in when it works. Does anyone know why this is?
If the value of a parameter change, like this:
parameter = new SomeValue();
then that change will only be seen by the caller using ref.
If instead you're changing the contents of an object which the caller passed a reference to, then that reference can be passed by value:
public void AppendHello(StringBuilder builder)
{
// This changes the data within the StringBuilder object that the
// builder variable refers to. It does *not* change the value of the
// builder variable itself.
builder.Append("Hello");
}
See my article on parameter passing for more information.
Note that if the parameter type is a struct instead of a class, then you won't be passing a copy of the reference to an object - you'll be passing the actual data itself. In that situation you'd need to use ref as well.
What do you mean by "modifying it". You can pass an object to a method and change its data, either by changing properties or adding elements to a generic list. However, you cannot change the actual object pointed to by that variable. In order to actually change, say Foobar to something else entirely, it needs to be passed by ref.