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.

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.

[Continued on Bits and Pieces, the new location of my blog]

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

כמתכנת 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);
}

Conditional Publication

This is a nice trick I ran into when going over the sourcecode for the XML-RPC.NET library:

#if (DEBUG)
public
#endif
void Serialize(…)

This lets you run your unit tests when developing, but remember to set your methods to private when releasing.

A new conditional assignment operator??

This one may have slipped beneath the radar, with all the new .NET 2.0 and WinFX and other improvements and APIs and language changes. It appears that C# 2.0 adds a new operator to the mix, and I never even knew it was there.

The operator is ??, and it’s a conditional non-null operator. Since that doesn’t really mean anything, I’ll simply and say that the ?? operator returns the left hand operand if it is non-null, otherwise it returns the righthand operand:

string a =  null;
string b = “String”;
Console.WriteLine (a ?? b); // Will output “String”.

This is shorthand for the common pattern we see using the ternary conditional operator, like this:

Console.WriteLine (a != null ? a : b);

which is in turn shorthand for:

if (a != null)
{
   Console.WriteLine(a);
}
else
{
   Console.WriteLine(b);
}

The ternary conditional is held by many to be a sin against nature and code readability, though I personally find it quite clear and convenient. The non-null conditional is a bit less clear – there’s nothing in its syntax to suggest an either/or relation. Perhaps it will clear things up. Perhaps it will lie unused and forgotten . Time will tell.

Note: For some reason, the MSDN library groups the ?? operator with the Assignment operators, rather than the Conditional operators. Strange.

Non-generic default values in C#? Why not?!

A relatively obscure new keyword in C# 2.0 is the default(T) keyword.
It’s shorthand for checking if the given generic parameter T is a value type or reference type. If it’s a reference type, it returns null. Otherwise it returns 0/false/0.0 or whatever the default value for the type is.

For some reason, though, it can only be used on generic parameters. Why can’t I use default(typeof(int)) to get 0? Or, more realistically, default(myUnknownType) to return the default value?

A workaround is to check if it’s a value type with reflection, but it’s cumbersome:

if (!myType.IsValueType)
{
   return null;
}
else
{
   return Activator.CreateInstance(myType);
}

Luckily, value types (including structs) always have a default parameterless constructor. We can’t even override it – it will always initialize all struct members to their default values.

This little code snippet can now be wrapper in some sort of function – call it Default() or GetDefault() or even @default() if you want to keep it as close as possible to the generic keyword.

It’s interesting to note that the generic keyword relies on the InitObj IL opcode to initialize the object. If we could embed IL directly in our code we could call this directly. We can do it via Reflection.Emit and DynamicMethods but I feel that’s going a bit far overboard when the solution above works just as well.

Bad compiler warnings when using anonymous methods for Predicate

I was sitting around munching some code, and needed to filter a list I had:


List<Whatever> list = // get list


outputList = list.FindAll(delegate(Whatever item)
{
   if (// blah blah)
   {
      return true;
   }
   else
   {
   return false
;
   }
}
);


(Ignore the greyed-out text for now).


When compiling, I got a strange error message:
“cannot convert from ‘anonymous method’ to ‘System.Predicate‘”.


This put me off for a few minutes while I tried checking code samples and such to make sure that this really SHOULD work. Only when I tried explicitly casting the anonymous delegate to a Predicate did I get a proper compiler error:
‘System.Predicate‘: not all code paths return a value’


Turns out my actual syntax error was being caught by the compiler and incorrectly reported.


Just a heads-up, in case it happens to anyone else.
Ladybug bug ID is FDBK50271, if anyone cares.

ParamArrays and CLS-compliance.

In my previous post, I noted that when I write this code in C#:


public void MyMethod (params object[] args) { … }


What I actually get in my IL is this:


public void MyMethod ([System.ParamArray]object[] args) { … }


I have this suspicion due to:
1) The fact that the C# compiler tells me to use params instead of the attribute
2) The fact that a function with the same signature except for the params keyword results in a duplicate signature
3) Because I opened up Reflector and saw it happening in the IL.


The params keyword in C# (and the ParamArray keyword in VB.NET) is a shorthand for applying the ParamArray attribute to the method. I assume the sole reason for the existence of the attribute is to notify the relevant compiler that when parsing a call to that function it should wrap the arguments in an array – nothing happens at runtime at all. It’s a language feature of C# and VB that is backed up by an attribute in the BCL, but does not have any representation in the CLR.


In the comments to that post, Thomas Tomiczek disagreed:

“Given that the ParamArrayAttribute is defined in System and HAS to be supported by the langauge compilers, basically, it is not a choice of the language. As such, it is not a language feature. It is a requirement.
WIth the same logic you could say that support for a lot of other things is optional – it is not. “

I am not sure I agree with this logic. Any .NET language has to support decorating the parameter with the ParamArray attribute of course, but I’m not sure that it’s required to be supported by all .NET languages.


I had a brief glance at the CLS specification and found this paragraph:









Argument lists


All


The only calling convention supported by the CLS is the standard managed calling convention; variable length argument lists are not allowed. (Use the ParamArray keyword in Microsoft Visual Basic and the params keyword in C# for variable number of arguments support.)


What this seems to mean is that the concept of variable length argument lists do not exist in the CLR, and the only way to pass a variable number of arguments is through arrays. VB.NET and C#, to name particular examples, provide us with language features (in the form of the params and ParamArray keywords) that save us the effort of creating arrays and do the wrapping-up for us.


The way I see it, the fact that it uses an attribute that’s defined in the System namespace, rather than language-specific namespaces (assuming one such would exist for C#) is just a result of the C# and VB teams working closely with the BCL designers.

A Better Obfuscation, or How To Write Code That Will Make Someone Kill You

The following code is perfectly valid C#, and compiles without errors:


int _;
_ = 5;


If we take it a bit further, we can do something like this:


int _, __, ___, ____;


_ = 5; __ = 10; ___ = 15; ____ = 20;


_ = __ – _ * ____ / ___;


Now I feel like I’m playing Hangman. I feel I should be filling in the blanks.


I’ve never run into anything like this in real code, I’m glad to say. But if Dotfuscator or any other obfuscating tool want to make their obfuscated code even harder to read, they should stop using the easy-to-remember “a”, “b” .. “aa”, “ab” variable names and switch to underscores. It’s horrible.

A silly little C# language feature request: .! operator

When we step back for a moment from our SOAs and Factories and Polymorphism, we have to admit that at the root of much of our code lie a hell of a lot of simple if/else statements. Like it or not, they're what makes our program logic tick.

All too often, though, our if logic is reversed – rather than checking for a true condition, we check for false:

if (!myDictionary.Contains(key))
{ } 

This syntax, while very common, isn't really easy to parse. While I can express my required logic in words as “if my dictionary does not contain key”, my syntax reads like the unintuitive “if not my dictionary does contains key” – I tend to think of my C# code in terms of natural languages. Usually English, even though it's not my native tongue.

So in order to bring C# more in line with my way of thought, I thought of having C# accept this sort of syntax:

if (myDictionary.!Contains(key))
{ } 

The .! operator is valid only before a boolean member, and inverts the return value, making it equivalent to the code above. Now the code reads the way it should and is just as easy to understand.

How does this sound? Any other supporters for this? Should I file a feature request on Connect?