Tag Archive for C#

When Not-True Doesn’t Equal False

There is a strangely common, reoccurring bug I’ve seen return, again and again, in most projects I’ve worked on in recent years. I call it the “Not True != False” bug, and it crops up, usually, when passing query parameters to a search service of some sort, when you want to search for entities who match a certain condition, and you end up not being able not to search by that condition.

Confusing? Let’s back up for a second.

One of the more common patterns in use is having our client run a query on our server by creating an object describing the query parameters. Call it the QueryFilter or SearchParams or QueryDTO or whatever. This class will encapsulate the parameters we want to search on:

public class PersonQueryFilter
{
    public string Name {get; set;}
    public bool IsVIP {get; set;}
}

Here, a simple query class that allows us to send a search to the server, returning a list of Person objects that match the given name, or that have the VIP property set to true. Simple, right? This is the common, straightforward and naive occurence of this bug that I see again and again. The developer needed a way to fetch all VIPs, so they added a field to specify VIPs.

Why is this a bug? Because as it stands, this class does not allow us to not search by IsVIP. We can ask for Persons that are VIPs. We can ask for Persons that aren't VIPs. But we can't ask for Persons regardless of whether they're VIPs. A boolean is simply that, a boolean. It doesn't encode information beyond yes/no. All matching entities must have either True or False.

This is a pernicious bug, but it will probably survive initial testing if the developer doesn't write comprehensive unit tests. That's because it will seem to work. "Write a feature that finds VIPs. Did it find VIPs? Yes, it did. Good, it works".

The solution to it is, of course, very simple. The opposite of "Find where X is True" is, in this case, not "Find where X is False", but "Find where X is irrelevant". For searching by Name, we can simply specify null as a marker for "don't search by this parameter". For our booleans, C# gives us the Nullable<bool> type (or bool?) to specify a third option for bool. Yes/No/Irrelevant. Other languages have their own solutions. Javascript can specify undefined or null for any data type. In Java you would probably use the Boolean object instead of the boolean primitive for many other reasons anyway (like generics), which can be set to null.

There are many workarounds. But many developers, especially relatively inexperienced ones, don't always think of the nullability of their search parameters.

Which is why I run into this bug again. And again. And again.

איך לשמור על אותיות גדולות וקטנות בעולם עוין

כמתכנת C#, אני רגיל לחשיבות של case sensitivity – משתנים בשם test ו-TEST הם שונים ונפרדים. גם ב-XML וב-JSON, שני הפורמטים הנפוצים לתעבורת מידע, נהוג להקפיד על case sensitivity בשמות של השדות/אלמנטים. ולרוב זה לא בעיה – אתה שומר עם case מסוים ואז קורא באותו case, והכל בסדר.

אבל היום נתקלתי בבעיה. במערכת מורכבת ומבוזרת שעליה אני עובד, מידע מעובד בקצה אחד, שדות נשמרים, והישות כולה נשמרת בתוך מסד נתונים מסוים, כשכל ערכי השדות שלה נשמרים תמיד ב-UPPERCASE. אבל היום הייתי צריך לשמור בתוך כמה שדות מידע שה-case שלו היה חשוב לשימור – במקרה הזה, שם קובץ מתוך שרת לינוקס עם מערכת קבצים רגישה ל-case, ובלוק של XML שגם בו הייתי חייב לשמור על גודל האותיות. אבל המנגנון היחיד שהיה לי לשמור את המידע בשביל להוציא אותו ולפעול עליו בקצה השני של המערכת לא משמר את ה-case של הנתונים. אז מה עושים?

המחשבה הראשונה שלי היתה לקודד את המידע ב-Base64, שמאפשר לקדד מידע שרירותי לתוך “שפה” של 64 תווים בלבד. אבל גם זו שפה גדולה מדי, וכוללת גם אותיות קטנות וגם גדולות, כך ש-Base64 הוא case sensitive גם הוא. אז השלב הבה היה לקודד את המידע לשפה “רזה” יותר, שאין בה את ההפרדה הזו בין אותיות גדולות וקטנות.

האופציה הבאה שלי היתה Base32 או Base36. שתיהן שיטות קידוד דומות ל-base64, אם כי פחות סטנדרטיות. הן לא case sensitive, שזה טוב, אבל בגלל שהן לא שיטת קידוד נפוצה, אין ב-.NET Framework תמיכה מובנית בהן, כמו שיש ל-base64. אפשר למצוא לא מעט מימושים, כמו כאן או כאן, אבל במקרה הזה לא רציתי להכניס קוד לא ידוע או ארוך מדי למערכת ברגע האחרון, למרות שברגע שירגע המצב קצת, יתכן שאחזור אליו.

אז האופציה הבאה אחרי כן היא פשוט לקודד את ה-bytes של הטקסט שלי כצמדי תווים הקסדצימליים – זו המרה די ישירה, ודרך די נפוצה להציג שטחי זכרון גולמיים. החסרון של זה הוא שזו שיטה בזבזנית הרבה יותר מ-base36 (שלא לומר base64), כי את אותו כמות מידע תדרוש יותר תווים באלף-בית ההקסדצימלי – שאפשר גם לכנות אותו base16 – מאשר בבסיסים הגדולים יותר. אבל היתרון הגדול הוא שיש כבר בתוך ה-framework דרך לעשות את ההמרה אוטומטית, מה שהופך את זמן הפיתוח – ובעיקר הבדיקות – לקצרצר הרבה יותר. אמנם המימוש הוא במחלקה קצת נידחת כחלק מהתמיכה ב-SOAP, אבל הוא שם, והוא נתמך מאז .NET 1.1 ב-2003. ועם האפשרות לכתוב את זה כ-extension method, אז השימוש בכלל נהיה קל מאד.

public static string ToHexBytes(this string plainText,
     Encoding encoding = null)
{
    encoding = encoding ?? Encoding.UTF8;
    var bytes = encoding.GetBytes(plainText);
    return new SoapHexBinary(bytes).ToString();
}

public static string FromHexBytes(this string hexText,
    Encoding encoding = null)
{
    encoding = encoding ?? Encoding.UTF8;
    var bytes = SoapHexBinary.Parse(hexText).Value;
    return encoding.GetString(bytes);
}

Quick and Dirty Code Timing

When looking to optimize our code, the first and best advice we should keep in mind is this: Measure. Don’t optimize before you know what takes time, and then only optimize where it makes sense.

Measuring can be done in many ways. Using Performance Counters, high-performance timers and stress tests. But often, especially in early iterations, we just want to get a ballpark figure for how long a bit of code takes. Maybe a low-level database call that gets used a lot, maybe as a wrapper in our initialization code to know what should be moved to lazy evaluation. In those cases, the quickest approach is to simply use .NET’s System.Diagnostics.Stopwatch class. Start it, stop it, and print out the timing.

So to ease this common pattern, and to illustrate, once more, the IDisposable pattern I so love to use, here’s a wrapper around Stopwatch, a TimedBlock class that lets you start a new using block around the code you want timed, and have the timing outputted to the Trace listeners. This can be seen in Visual Studio’s Output window, or in any Trace listener you care to add.

Here is the code:

public class TimedBlock : IDisposable { private readonly string _blockName; private readonly Stopwatch _timer; private static int _anonymousBlockCounter = 1; public TimedBlock(string blockName = null, params object[] arguments) { _blockName = !string.IsNullOrEmpty(blockName) ? string.Format(blockName, arguments) : "Anonymous #" + _anonymousBlockCounter++; _timer = new Stopwatch(); _timer.Start(); } public void Dispose() { if (_timer != null && _timer.IsRunning) { _timer.Stop(); Trace.WriteLine(string.Format("{0} took {1} seconds.", _blockName, _timer.Elapsed.TotalSeconds), "Timer"); } }

  public static TimedBlock Start(string blockName = null, params object[] arguments) { return new TimedBlock(blockName, arguments); } }

And here’s the usage:

using (new TimedBlock("Potentially slow action #{0} ", actionId)) {

DoSlowOperation(); }

 

Notes:

  • Just for kicks, I added two ways to initialize the TimedBlock. Either with new TimedBlock() or with TimedBlock.Start(). They are identical, merely stylistically different.
  • The block is initialized with a name. This is used to find it in the trace output. If no name is passed, a default name will be used.

Have fun with it. Remember, it’s just a quick and dirty timesaver. Use it well.

Not-So-Lazy Static Constructors in C# 4.0

A coworker pointed me towards an interesting blog post by John Skeet about the changed behavior of static constructors in C# 4.0 (yes, I know, it’s been a few years now, but I never ran into it).

It seems that C# 4.0 now tries to be lazier when instantiated static fields. So if I have a side-effect free static method that doesn’t touch any members, calling it will not bother initializing the static fields. From Skeet’s post:

  1. class Lazy
  2.     {
  3.         private static int x = Log();
  4.         private static int Log()
  5.         {
  6.             Console.WriteLine("Type initialized");
  7.             return 0;
  8.         }
  9.         public static void StaticMethod()
  10.         {
  11.             Console.WriteLine("In static method");
  12.         }
  13.     }

Calling StaticMethod() will print “In static method”, but will not print “Type Initialized”!

This was a bit worrying. John Skeet said it shouldn’t impact existing code, but we were not so sure. Imagine a class whose static constructor does some unmanaged initialization work (creates a Performance Counter, for instance) while the static method  writes to the counter. This could potentially cause a hard to find exception, since our expectation was that static constructors can be relied upon to always be called first.

So we ran a quick test (and by “we” I most mean Amir), and it seems that this behavior isn’t as problematic as we thought. Look at this code, adding a static constructor to the class above:

  1. class Lazy
  2.     {
  3.         private static int x = Log();
  4.         private static int Log()
  5.         {
  6.             Console.WriteLine("Type initialized");
  7.             return 0;
  8.         }
  9.  
  10.         static Lazy()
  11.         {
  12.             Console.WriteLine("In static constructor");
  13.         }
  14.  
  15.         public static void StaticMethod()
  16.         {
  17.             Console.WriteLine("In static method");
  18.         }
  19.     }

 

The only difference is that we have an explicit static constructor, rather than the implicit one that initializes the field. Unlike the first test case, in this case calling StaticMethod() did call the static constructor, and we could see “In static constructor” printed before “In static method”. The compiler is smart enough to see that we have an explicit constructor defined, so that means we want it to be called, and it will be called. This was reassuring.

But wait, there’s more! It seems that once type initialization was triggered by the presence of the explicit static constructor, it went all the way. Even the x parameter was initialized, the Log() method was called, and “Type Initialized” was printed to the console, even before the static constructor. This was the behavior I was used to, where static field initializations are added to the beginning of the .cctor.

To summarize, the new lazy type initialization behavior for C# 4.0 is interesting, since it allows static classes that contain only side-effect free methods (for instance, classes containing popular Extension Methods) to avoid expensive and unnecessary initializations. But it was designed smartly enough to recognize when initialization is explicitly desired, and be a bit less lazy in that case.

(And thanks again to Igal Tabachnik and Amir Zuker)

האם עוד צריך את VB.NET לתכנת מול אופיס?

עברו כמה שנים מאז שעבדתי עם Visual Basic.NET, והייתי בטוח שבימינו, ב-2013, נגמרו כבר הויכוחים של “איזו שפה יותר טובה”. שתיהן שפות עם יכולות דומות, והבחירה ביניהן היא בעיקר העדפה סגנונית. אבל מידי פעם אני עדיין רואה בפורומים או ב-Stack Overflow שאלה בנוגע ליתרונות של שפה אחת על השניה, וספציפית על יכולות ה-COM Interop של VB. האם היא באמת שפה נוחה יותר?

המצב טרום .NET 4.0

לפני .NET 4.0 (שיצאה, יש להזכיר, לפני כמעט 3 שנים), התשובה היתה “כן”, אם כי “כן” קצת דחוק. VB הגיעה מתוך עולם ה-Late Binding, ולא היה לה בעיה להעביר לרכיב רק חלק מהפרמטרים שהם צריכים, ולדאוג לשאר לברירות מחדל מאחורי הקלעים. היתרון הזה היה בולט במיוחד כשעובדים מול אובייקטים של אופיס, שמכילים מתודות שמקבלות חמישה, עשרה, ולפעמים שישה-עשר פרמטרים אופציונאליים, כשברוב המקרים אנחנו נרצה להעביר רק אחד או שניים מהם, אם בכלל. ההבדל בין C# ל-VB במקרה כזה הוא ההבדל בין הקוד הזה ב-C#:

Code Snippet
  1. myWordDocument.SaveAs(ref fileName, ref missingValue,
  2.                  ref missingValue, ref missingValue,
  3.                  ref missingValue, ref missingValue,
  4.                  ref missingValue, ref missingValue,
  5.                  ref missingValue, ref missingValue,
  6.                  ref missingValue, ref missingValue,
  7.                  ref missingValue, ref missingValue,
  8.                  ref missingValue, ref missingValue);

לבין זה ב-VB:

Code Snippet
  1. MyWordDocument.SaveAs(FileName: fileName)

שזה, אתם חייבים להודות, הבדל לא קטן.

אבל מצד שני, לא כל ממשק COM עובד ככה. למען האמת, בכל שנותי אני חושב שנתקלתי בסגנון כתיבה הזה רק בספריות של אופיס, ולא בשום רכיב אחר, בין אם של מיקרוסופט (כמו רכיבי DirectShow שאיתם עבדתי לאחרונה) או של חברות אחרות. ברוב המקרים, לעשות COM Interop ב-C# פשוט באותה מידה כמו ב-VB.

.NET 4.0 – גם C# זוכה ליחס

היתרון הקטן הזה של VB נהיה גם הוא פחות רלבנטי החל מ-C# 4.0 ו-Visual Studio 2010, משתי סיבות:

הראשונה היא מילת הקסם שהתווספה לה לשפה, dynamic. כשאנחנו מגדירים אובייקט כדינאמי, אנחנו מוותרים על הרבה מה-static type checking שהקומפיילר עושה בשבילנו, ונותנים למנגנון ה-late binding (שסופח ל-C# באמצעות ה-DLR, ה-Dynamic Language Runtime שנבנה לתמוך בשפות דינאמיות כמו Python או Ruby) לעשות בשבילנו את העבודה ב-runtime. מכיוון שיש late binding, אפשר להתעלם מהפרמטרים המיותרים ולתת ל-DLR להבין לבד מה לחבר לאיפה. אפשר למצוא הסבר כללי על שימוש ב-dynamic במאמר הזה, והסבר יותר ספציפי על השימוש בו ל-COM Interop במאמר הזה.

אבל אם אנחנו שקלנו לעבור ל-VB רק בשביל לעבוד מול רכיבי אופיס, אז C# 4.0 מאפשר לנו להקל על החיים גם בלי לצלול לעולם העכור של dynamic languages. אנחנו עדיין לא יכולים להתעלם מ-ref parameters במתודות של מחלקות, אבל אנחנו כן יכולים להתעלם מהפרמטרים הללו בקריאות למתודות על interfaces. אני לא יכול להגיד שאני מבין לגמרי למה זה ככה (טרם התעמקתי) אבל זה אומר שאם מה שיש לנו ביד זה לא אובייקט DocumentClass של אופיס, אלא interface מסוג Document, אז אפשר לקרוא למתודות שעליו כמו ב-VB.

לנוחותינו, ספריות ה-Interop של אופיס חושפות לנו את ה-interfaces האלה, דרך property בשם InnerObject שיש על רוב האובייקטים המעניינים. (כן, זה property בשם InnerObject שחושף את ה-Interface. אני יודע. זה מבלבל. זה מה יש). אז את הקוד שכתבנו למעלה  אפשר להחליף, ב-C# 4.0, בזה:

Code Snippet
  1. myWordDocument.InnerObject.SaveAs(FileName: fileName);

וזהו! אמנם לא כל אובייקט של אופיס זוכה ל-InnerObject הזה, אבל המרכזיים והגדולים (שהם גם אלה עם המתודות המפלצתיות) דווקא כן. ואם אין ברירה, נעבוד גם עם dynamic – או עם Missing.Value.

אז מתי בכל זאת VB?

כל המלל לעיל לא נועד לשכנע מישהו לבחור דווקא ב-C# או דווקא לא ב-VB. שתי השפות יכולות לעשות פחות או יותר כל אחת את מה שהשניה יכולה לעשות, והבחירה בה צריכה להיות של העדפה אישית לסגנון כתיבה, לא בגלל יכולת קריטיות לכאן או לכאן. זה מה שניסיתי להעביר כאן – כמו ש-VB יישרה קו עם C# לאורך השנים בכמה פיצ’רים שהיו חסרים, כך גם C# השלימה את החסר לה בנוגע לעבודה עם אופיס. הבחירה היא, שוב, סגנונית בלבד.

ArcGIS–Getting the Legend Labels out

Working with ESRI’s ArcGIS package, especially the WPF API, can be confusing. There’s the REST API, the SOAP APIs, and the WPF classes themselves, which expose some web service calls and information, but not everything. With all that, it can be hard to find specific features between the different options. Some functionality is handed to you on a silver platter, while some is maddeningly hard to implement.

Today, for instance, I was working on adding a Legend control to my map-based WPF application, to explain the different symbols that can appear on the map.

This is how the legend looks on ESRI’s own map-editing tools:

 

but this is how it looks when I used the Legend control, supplied out of the box by ESRI:

 

Very pretty, but unfortunately missing the option to display the name of the fields that make up the symbology.

Luckily, the WPF controls have a lot of templating/extensibility points, to allow you to specify the layout of each field:

   1: <esri:Legend>

   2:     <esri:Legend.MapLayerTemplate>

   3:         <DataTemplate>

   4:              <TextBlock Text="{Binding Layer.ID}"/>

   5:         </DataTemplate> 

   6:     </esri:Legend.MapLayerTemplate>

   7: </esri:Legend>

but that only replicates the same built in behavior. I could now add any additional fields I liked, but unfortunately, I couldn’t find them as part of the Layer, GraphicsLayer or FeatureLayer definitions. This is the part where ESRI’s lack of organization is noticeable, since I can see this data easily when accessing the ArcGis Server’s web-interface, but I had no idea how to find it as part of the built-in class. Is it a part of Layer? Of LayerInfo? Of the LayerDefinition class that exists only in the SOAP service?

As it turns out, neither. Since these fields are used by the symbol renderer to determine which symbol to draw, they’re actually a part of the layer’s Renderer. Since I already had a MyFeatureLayer class derived from FeatureLayer that added extra functionality, I could just add this property to it:

   1: public string LegendFields

   2: {

   3:     get

   4:     {

   5:         if (this.Renderer is UniqueValueRenderer)

   6:         {

   7:             return (this.Renderer as UniqueValueRenderer).Field;

   8:         }

   9:         else if (this.Renderer is UniqueValueMultipleFieldsRenderer)

  10:         {

  11:             var renderer = this.Renderer as UniqueValueMultipleFieldsRenderer;

  12:             return string.Join(renderer.FieldDelimiter, renderer.Fields);

  13:         }

  14:         else return null;

  15: }

For my scenario, all of my layers used symbology derived from a single field or, as in the examples above, from several of them. The renderer even kindly supplied me with the comma to separate the fields with. Now it was a simple matter to get the Legend control in line – assuming that it was bound to a collection of MyFeatureLayer:

   1: <esri:Legend>

   2:     <esri:Legend.MapLayerTemplate>

   3:         <DataTemplate>

   4:             <StackPanel>

   5:                 <TextBlock Text="{Binding Layer.ID}"/>

   6:                 <TextBlock Text="{Binding Layer.LegendFields}" Margin="10,0,0,0" TextStyle="Italic"/>

   7:             </StackPanel>

   8:         </DataTemplate>

   9:     </esri:Legend.MapLayerTemplate>

  10: </esri:Legend>

and get the look I wanted – the list of fields below the layer name, indented.

The Case of the Expected Unexpected Exception

“NUnit is being problematic again”, they told me when I came to visit the project. “When running unattended it’s not catching assertions properly and the test is coming up green, but when stepping through in the debugger, it works fine.”. It’s nice, when getting a passing test is acknowledged as a bad thing, at least when you don’t expect it to be. In this case, though, the fault wasn’t really with NUnit.

  1: [Test]
  2: [ExpectedException]
  3: public void DoTheTest()
  4: {
  5:     _myComponent.RunMethod();
  6:     Assert.IsTrue(_myComponent.EverythingIsFine);
  7: }

“It’s simple. Either the method throws an exception, or at the very least – the EverythingIsFine property won’t be set to “True”, so the assert will catch the problem. But in their case, no exception was thrown and Everything wasn’t Fine,  but the Assert call wasn’t raising a red flag – unless they stepped through, in which case it did. What’s going on?

The basic problem is that to many developers, NUnit is a kind of magic. You write a self-contained little bit of code, the [Test] method, but you don’t call it yourself, you don’t get a feel for the whole execution flow. The result – developers don’t exercise the same sort of judgement they do on their own application code.

The root of the problem here is that the [ExpectedException] attribute told NUnit to pass the test if an exception is thrown. NUnit’s Assertion utilities, however, use exceptions as the mechanism for failing tests – when an assertion is hit, it raises an exception – it can be an AssertionException. For various mock frameworks, it can be an ExpectationException. It doesn’t matter – it’s these exceptions that make the test fail, and not some behind-the-scenes magic. Because the test had an open-ended [ExpectedException] attribute, these exceptions were caught, fulfilling the condition, and NUnit was happy.

What can we do to avoid this?

  • Be explicit. Don’t try to catch ALL exceptions with [ExpectedException]. If you’re expecting an exception, you’re probably expecting a specific exception. Specify it.
  • Be aware of how your tools work. If NUnit works by throwing an exception, don’t wrap it with a try/catch. Your tests are C# code too, as is the plumbing to enable it. It plays by the same rules.