tags:

views:

228

answers:

5

For the first time i created a linq to sql classes. I decided to look at the class and found this.

What... why is it doing if(sz !=sz2) { sz = sz2; }. I dont understand. Why isnt the set generated as this._Property1 = value?

 private string _Property1;
 [Column(Storage="_Property1", CanBeNull=false)]
 public string Property1
 {
  get
  {
   return this._Property1;
  }
  set
  {
   if ((this._Property1 != value))
   {
    this._Property1 = value;
   }
  }
 }
+5  A: 

It only updates the property if it has changed. This is probably based on the assumption that a comparison is cheaper than updating the reference (and all the entailed memory management) that might be involved.

GrayWizardx
That, and strings are value types creating lots of unnecessary copies is always a bad thing... GC wise...
Jason D
@GrayWizardx: setting a field won't cause propertychange notifications. @Jason D: strings are not value types, but you're probably right that it's related to GC costs - see my answer.
Joe
This isn't entirely accurate. If there are no calls to send property changing/changed notifications inside the `if` block then wrapping the assignment to the backing field isn't preventing them from being called; they're not being called whether or not the `if` is there. Now, the usual LINQ-to-SQL generated properties do have calls to `OnPropertyChanging` and `OnPropertyChanged("PropertyName")` so I suspect that a setting was turned off to disable these notifications and if that is the case, the code-generator kept it simple by still including the `if` blocks even though they're unnecessary.
Jason
Remove assumption about property change notification
GrayWizardx
+3  A: 

Setting a field won't cause property change notifications, so that's not the reason.

I would guess that this design choice was driven by something like the following:

That string is an immutable reference type. Therefore the original and new instances are interchangeable. However the original instance may have been around longer and on average may therefore be slightly more expensive to collect (*). So performance may be better if the original instance is retained rather than being replaced by a new identical instance.

(*) The new value has in most cases only just been allocated, and won't be reused after the property is set. So it is very often a Gen0 object that is efficient to collect, whereas the original value's GC generation is unknown.

If this reasoning is correct, I wouldn't expect to see the same pattern for value-type properties (int, double, DateTime, ...).

But of course this is only speculation and I may be completely wrong.

Joe
A: 

Looks like there's persistence going on here. If something is using reflection (or a pointcut, or something) to create a SQL UPDATE query when _Property1 changes, then it'll be very much more expensive to update the field than to do the comparison.

Jeremy McGee
How can reflection or pointcut detect that a variable is changed? Can you give me a link? i did a quick search and didnt find anything (i found more java then C# and i used C# keyword in google)
acidzombie24
+4  A: 

Where are you seeing that? The usual LINQ-to-SQL generated properties look like the following:

private string _Property1;
[Column(Storage="_Property1", CanBeNull=false)]
public string Property1 {
    get {
        return this._Property1;
    }
    set {
        if ((this._Property1 != value)) {
           this.OnProperty1Changing(value);
           this.SendPropertyChanging();
           this._Property1 = value;
           this.SendPropertyChanged("Property1");
           this.OnProperty1Changed();
       }
    }
}

And now it's very clear that the device is to avoid sending property changing/changed notifications when the property is not actually changing.

Now, it turns out that OnProperty1Changing and OnProperty1Changed are partial methods so that if you don't declare a body for them elsewhere the calls to those methods will not be compiled into the final assembly (so if, say, you were looking in Reflector you would not see these calls). But SendPropertyChanging and SendPropertyChanged are protected methods that can't be compiled out.

So, did you perhaps change a setting that prevents the property changing/changed notifications from being emitted by the code generator?

Jason
+1 - without having examined the generated code, I suspect that this explanation (property change notifications disabled, and the 'if' block left in place) is more likely that the GC micro-optimization I speculated about in my answer.
Joe
@Joe: Yes, I largely suspect that this is the answer. As the LINQ-to-SQL generator will sometimes put other code in that block (such as if the property being changed is a PK or FK) I would guess that for ease of design the `if` block is emitted regardless. (Or it wasn't intended and now it's a "feature.")
Jason
A: 

It comes from Heijlsberg's ObjectPascal root.... at least that's how most of the Borland Delphi VCL is implemented... ;)

invarbrass