Copies and boxes and performance, Oh My.This caught me and members of a client team recently, so I thought I would share it. In a Windows application, we created a simple value type to store a couple properties. Something like this:
public struct WeatherObservation
{
private int _low;
public int Low
{
get { return _low ; }
set { _low = value; }
}
private int _high;
public int High
{
get { return _high; }
set { _high = value; }
}
}
We had a form that asked the user for input. We utilized Windows Forms Binding:
textBoxLow.DataBindings.Add( "Text", this._weatherData, "Low" );
textBoxHigh.DataBindings.Add( "Text", this._weatherData, "High" );
And, it did not work. The user’s changes never were stored back into the _weatherData structure. Why?
Well, I’m not going to keep you waiting, I’ll dive right into the answer. The problem is that WeatherObservation is a struct, not a class. Structs are value types. They are passed by value, not by reference. More than that, the .NET environment boxes structs to use them where a System.Object is expected.
Here, the method signature for DataBindings.Add is
void Add( string propertyName, object DataSource, string DataMember );
The data source member , a struct, must get boxed in order to match the signature of the Add method. That boxing makes a copy. The databinding infrastructure dutifully modifies the copy whenever the user makes changes. But nowhere are those changes propagated from the copy back to the original object. The bottom line is that structs just can’t participate in read/write databinding. You must use reference types.
One best practice will help you avoid running into this situation yourself. Structs should be immutable. Then, you’ll never expect to use them in read/write situations. This does not prevent you from using members of a struct for read only databinding. The initial values are copied to the control, the same way they are copied when boxed.
You can even use structs as the final storage medium for databainding. When you need to use read/write databinding with a struct, the struct (which should be immutable, remember) should be stored as a member of a reference type. Then, you bind the outer reference type (as the datasource) to the control. The value type can be the datamember, or you can provide access to individual properties of the value type through the outer reference type.
I’ll close by addressing one common question: Why use value types at all? In many cases, the right answer is to avoid value types. It’s certainly simpler. But value types can and do provide some important performance benefits. The small snippet of code above isolated the behavior I wanted to show you, but the actual application was analyzing experiment results for an engineering application. Each experiment run generated several thousand points. The engineers were working with over 500,000 elements in one session. And, the application performs quite a few numerical calculations on all the values to interpret the experiment’s results. Collections that large do exhibit serious performance degradations when all the data are stored in reference types. The memory management issues do matter. Your mileage may vary, and you should always benchmark these kinds of performance issues. But, in general, I’ve found that the value types do offer performance benefits for datasets over 10,000, and then only when you are performing calculations that require you to examine each of the elements individually.
I've opened a blog for reader Q & A (and errata *sigh*).I’ve added the first reader Q & A item to the Effective C# book blog:
In the section on Conditionals you say that in order to create a method that will fire if more than one condition is true (logical AND), you need to use
#if (VAR1 && VAR2)
#define BOTH
#endif
However, it is possible to chain the conditionals together (according to MSDN, anyway…)
<QUOTE from=”MSDN”>
[Conditional("A")] public static void IfAandB( )
{
AandBPrivate( );
}
[Conditional("B")] static void AandBPrivate( )
{
/* Code to execute when both A and B are defined... */
}
Call IfAandB; if both A and B are defined, AandBPrivate will execute.
</QUOTE>
Is there any reason to use your method above the MS one?
You can read the full answer here:
The Effective C# Book BlogDiscussions on Effective C#
The Effective C# Book Blog RSS FeedSubscribe for news and information
The first questionConditional attributes
Hey, he still might get 9 out of 10 predictions correct.Don Box released his predictions for 2005:
http://pluralsight.com/blogs/dbox/archive/2004/12/29/4113.aspx (See item 7):
Miguel de Icaza will leave Novell and join Google.
Miguel will announce he's bored and will start a public bidding war. Microsoft will step aside as Miguel goes to Google and brings C# with him. The biggest upside is that Josh Bloch will finally write the book he's destined to write - Effective C#.
Effective C# has been published, but it's not by Josh Bloch: http://www.awprofessional.com/title/0321245660
Don's PredictionsCheck out Item 7
Effective C# homepageWill the real Effective C# please stand up
7-11 inches of snow expected.On the theory that a signifcant portion of my readers are in the S.E Michigan area, I'm sending this note to let everyone (all 5 of them) know that AACS and Borders have postponed the Effective C# talk and book signing this evening.
The theory is that the Winter Storm warning, and the 7 - 11 inches of snow will depress turnout.
Expect updates once the new date is set.
I'll be speaking about Effective C#, and signing booksAddison-Wesley published a notification about my speaking engagement at the downtown Border’s in Ann Arbor this coming Wednesday evening at 7:30 pm.
If you’re in the area, I hope you attend. It's free.
Addison-Wesley's announcementAt Borders, January 5th
The AACS announcementincluding the talk abstract
Information about the Borders in Ann ArborDriving Directions and other information
Peter Himshoot (a fellow RD) comments on Effective C#
Peter Himshoot, another Regional
Director, has written an entry
in his blog about Effective C#.
He says some very nice things, including "So for anyone interested in
improving their C# (and VB.NET too B.T.W.) and write code that is correct and
executes faster, I can recommend this book!"
Thank you!
Peter's blogTalking about .NET, BizTalk Server 2004 'n stuff
The Effective C# EntryWhat Peter had to say
The Effective C# HomepageAddison-Wesley's page about Effective C#