When you pass parameters in VB, you use the ByVal and ByRef keyworks. The default in VB is ByRef with a nuance (see ByRef Parameters Passed by Value) In C#, no keyword means by value and alternatively, you use the ref keyword to pass a reference.
The key difference is that when you pass a variable by value , you are just passing a copy. The originating variable cannot be replaced.
When passing by reference, you are working with the actual variable and can replace it.
The part that frequently evades developers is that if the value is a reference type (i.e. does not contain it’s values directly compared to, for example, an int which does) you can modify those related values whether you pass by reference or by value.
Now let’s look at this with respect to an ObjectContext being passed as a parameter. An ObjectContext has it’s own values but also has references to other values (e.g. the ObjectStateEntry types that it maintains to keep track of entities).
Whether you pass the context by value or reference, the entities that the context is tracking will be impacted when you execute queries or call SaveChanges with the context.
When passing it by value you won’t replace the context, e.g, passedinContext=new MyEntities() won’t affect the originating context.
When passing it by ref, you CAN replace the context e.g., passedinContext=new MyEntities() will reinstantiate the originating context. And if you replace the context, you will lose ALL of the state information for the currently tracked entities. Those entities will be orphaned – just sitting in memory with nobody tracking them and if you do reattach them to the new instance of the context, they will all be unchanged.
That’s a big problem.
So unless you are trying to achieve some specific behavior, you should definitely pass byval. In fact you should define your method signature that takes the parameter to ensure that you are passing by value.
Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!
4 thoughts on “Passing around an ObjectContext: by value or reference?”
Maybe i’m nitpicking, but String is actually a reference type. It’s immutable so it cannot be modified, but it’s passed by reference.
Thanks. I actually do know that so that’s embarrassing ;). And I knew I was going to get something wrong in that refresher. FIxed 😉
I agree completely, in fact I think passing parameters ByRef is something to be avoided. Most developers don’t understand the difference, especially when you mix in reference and value types, and very few expect return values through the parameters.
Isn’t Integer.TryParse the ugliest method in the BCL?
I think I agree (now) with the idea of passing the context ByVal, so I’m grateful to have it corroborated.
However, I disagree with the notion that “passing parameters ByRef is something to be avoided” and I think it is vital that all .NET developers understand the difference, especially if they are going to be using web services.
I have experience of developers being confused when they call a web service into which they pass an object ByVal and find that changes they expected to be made inside the object have apparently vanished after the call returns.
Furthermore, developers need to understand that the parameter profile of a procedure is a kind of contract, often not easily changed, and that whilst the current implementation may not need a parameter to be ByRef, some future implementation may require it (unavoidably).