What should be in C#

Generic Indexers

C# has generic classes, interfaces, and methods. What about generic indexers?

Class indexers are properties (has a get accessor):

public object this[string key]
{
	get { return new Object(); }
}

Just as indexers are advantageous and so are generics, having generic indexers would be also advantageous:

public T this<T>[string key]
{
	get { return default(T); }
}

Properties cannot be generic in C#, ergo no generic indexers. While I haven’t needed a generic property yet (whether to use a property or method is mostly preferential, so a generic method can always be used instead), I have had scenarios where a generic indexer would be advantageous.

For example, wouldn’t it be cleaner to do this:

var settings = new Settings();
int timeout = settings<int>["CacheInMinutes"];

Than to have to unbox or convert, as is the case without generic properties, like this:

var settings = new Settings();
int timeout = int.Parse(settings["CacheInMinutes"]);

I, for one, think so. Why aren’t there generic properties? I’m not sure. A conscious language design decision? Some logistical conflict in the compiler? Maybe someone more informed knows.

Static Local Variables

This is one example where I think VB got it right and C# got it wrong.

Let’s say I have a class with a method, and that method needs a static variable. Only that method (one method) is going to use the static variable though:

	
/// <summary>
/// Uber complex class with all sorts of instance fields,
/// properties, static methods, interface methods, etc.
/// </summary>
public class Feed
{
	private static readonly string[] adultTerms = ...;

	public bool IsAdult
	{
		get { return Feed.IsAdultCheck(this); }
	}

	public static bool IsAdultCheck(Feed feed)
	{
		foreach(var value in Feed.xmlElements)
		{
			if (Feed.adultTerms.Contains(value))
				return true;
		}
		return false;
	}
}

(Ignore the fact that an array and Array.Contains() is used for/on adultTerms instead of a Dictionary, and that “value” isn’t ToLower()ed. I’m trying to illustrate a point here, nitpicker!)

Only IsAdultCheck() needs access to the value of adultTerms, but in C#, the whole class can have access to that variable. Hiding it from the rest of the class, within the method, removes noise from the class. When examining a class you’re not familiar with for the first time, the less glutter, the better.

Not convinced? What if IsAdultCheck() is just the beginning—there are other methods that also have their own groups of static fields?

Would you rather see this, if you had to work with the Feed class:

public class Feed
{
	#region These could all be static locals!

	// Used by IsAdultCheck()

	private static readonly string[] adultTerms;

	// Used by NextPaginated()

	private static int pageCurrent;
	private static int pageStart;
	private static int pageEnd;
	private static string paginatedFeedUrl;

	// Used by Whatever()

	public static bool whateverSetting;
	public static string whateverSetting2;
	public static DateTime whateverSetting3;

	#endregion

	public static string NextPaginated(Feed feed)
	{ /* ... */ }
	
	public static string IsAdultCheck(Feed feed)
	{ /* ... */ }

	public static void Whatever()
	{ /* ... */ }
}

Or would you rather have all these private static variables encapsulated in each method in which they’re exclusively used, as local static variables?

Like I said, VB got it right when static local variables were included, starting with VB 3.0. adultTerms can be encapsulated in IsAdultCheck():

	
Public Class Feed
	Public Shared Function IsAdultCheck(ByRef feed as Feed) as Boolean
		Static adultTerms() as String = ...
		
		For Each term as String in adultTerms
			If term.Contains(term) Then Return True
			Return False
		Next
	End Function
End Class

What’s the argument against including static local variables in C#? I understand the need to differentiate the two .NET languages, but c’mon, I know a good thing when I see it! In

Update: I emailed the C# Team Project Manager, Mads Torgenson, to find out why the decision was made not to have static local variables. I’ll paraphrase his response: “There’s no need. Create a new class and encapsulate the method(s) and the static variable(s) in there.” In general I agree that this is a good idea, but then I wouldn’t have anything to complain about.

Full Support for Variable Declaration in Statements

Here’s some valid C#:

foreach(var url in urls)
	// ...
for(int i = 0; i < length; i++)
	// ...
using(var buffer = new MemoryStream())
	// ...

Notice how all three “for,” “foreach,” and “using” statements allow the declaration of a variable in them? They must be special, for some odd reason. Because here’s some C# that’s a no-go:

if ((var metaKeywords = AppSettings["MetaKeywords"]) != null)
	Page.SetMetaTags(MetaTags.Keywords, metaKeywords);

What’s good about the for loops and the using statement above is that since the variables declared in the statements are only going to be used within the scope of the statements, they’re inaccessible to the rest of the method in which the statements resides. This is another example of encapuslation that reduces extraneous noise, much like when I wrote of method-local static variables above. If the rest of the method doesn’t need to use the variables, they shouldn’t be able to.

Just as these snippets wouldn’t be advisable if “i” and “buffer” were only used within the scope of the statements:

var i = 0;
for(; i < length; i++)
	// ...
var buffer = new MemoryStream();
using(buffer)
	// ...

And just as this wouldn’t make sense—and isn’t even possible:

string url;
foreach(url in urls)
	// ...

Neither does it make sense to do the following if “metaKeywords” isn’t going to be used outside the scope of the if statement (which you currently have to do in C#):

var metaKeywords = AppSettings["MetaKeywords"];

if (metaKeywords != null)
	Page.SetMetaTags(MetaTags.Keywords, metaKeywords);

The reason an inline variable declaration in an if statement is probably illegal, as someone pointed out to me, is that a lot of C and C++ code is terse—like a competition for fewest lines. The downside is readability and maintainability, which go hand-in-hand. Sure, it’s cool to refactor 10 lines into two, but it’s usually not so cool when a different developer goes in and tries to debug or modify that code. But if the readability of a for statement, for example, isn’t an issue in C#, then it seems rather arbitrary to me that if statements would be.

Sure, there’s room for abuse, but I don’t need C# to save me from myself. Perhaps C# needs to save itself from developers, such as those from dynamic or scripting languages, where this practice is more common, and clean code is sparser.

Non-integral Enums

Ever find yourself switch()ing an enum, and assigning different values to an object based on the case of that enum? For example, say we’ve got this enumeration:

enum AmericanHoliday
{
	NewYearDay,
	IndependenceDay,   
	Christmas
}

And depending on the AmericanHoliday selection, we have a switch that returns a corresponding date:

private DateTime GetHolidayDate(AmericanHoliday holiday)
{
	switch (holiday)
	{
		case AmericanHoliday.NewYearDay:
			return DateTime.Parse("1/1");
		case AmericanHoliday.IndependenceDay:
			return DateTime.Parse("7/4");
		case AmericanHoliday.Christmas:
			return DateTime.Parse("12/25");
		default:
			throw new NotImplementedException();
	}
}

We have this switch because AmericanHoliday enumerations are can only be byte, sbyte, short, ushort, int, uint, long, or ulong. The problem with integral-only is that a switch (or if) statement has to be used if you want that enum to represent anything other than an integral type (i.e. a number).

But what if we could use different types, that didn’t have to be constants, in an enum, like a DateTime?

enum AmericanHoliday
{
	NewYearDay = DateTime.Parse("1/1"),
	IndependenceDay = DateTime.Parse("7/4"),
	Christmas = DateTime.Parse("12/25")
}

We could eliminate the conversion from an enum to a DateTime performed in GetHolidayDate(), and simply write:

DateTime holidayDate = AmericanHoliday.NewYearDay; 

Or how about we had an enum that represented an error:

enum AccessDeniedReason
{
	UnknownUser = "The specified user is unknown.",
	InvalidPassword = "The specified password was invalid.",
	AccountDeactivated = "The account has been deactivated."
}

There are ways of achieving something similar in C#, but none of the workarounds are very good. Perhaps implementing such a thing just isn’t practical in a statically-typed language.

kick it on DotNetKicks.com

About these ads

6 Comments »

  1. Zack Owens said

    Ahh, some very nice things here. I especially like the var declaration in statements. Nice feature.

    Here’s my suggestion. I personally HATE typing out KeyValuePair foo. It looks pretty dirty in code. What about int, int foo. Or something like that. For nullables, for example, we have float? which can also be written Nullable. Another way to write this could be int^int or int#int or int@int, int-int, whatever. That’s my 2 cents.

  2. Matt said

    Nice post. Very interesting take on things.

    Generic properties — I don’t think that this is possible since you’re essentially asking the compiler to differentiate between methods (get_PropertyName and set_PropertyName as they’re implemented under the hood) based on their return value, not on their inputs. I think that C# can only overload methods based on the types of the inputs (the method signature) but not the types of the inputs and outputs combined.

    Typedef — I think this is possible to some degree by using the “using” statement. Unfortunately it’s only local to the current file. Just stick “using Coordinate = System.Collections.Generic.Dictionary;” at the top of your file.
    I agree, it would be awfully nice if this were implemented project-wide instead of per-file.

    Enums — Right, that would be nice. Typically if you want to attach strings to enums, you can slap a DescriptionAttribute on them and use the EnumDescConverter.
    http://www.codeproject.com/KB/cs/enumdescconverter.aspx

  3. As far as generic indexers, couldn’t you use a construct like the one listed here:

    http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx

  4. Janell said

    We are impressed in that website, very I am a fan.

  5. Ava said

    I’m across this in this write-up, I must say i think this web page wants far more consideration. I’ll most probably be again to read far more, nice one for that info.

  6. You may have thought about including more than merely your articles regularly?
    I’m referring to, everything you think are important and everything. But think of if you added is not only visuals or videos to allow for your website content more, “pop”! Your article is incredible but images and videos, this blog – could undeniably be among the many greatest in its bristling field. Good blog!

RSS feed for comments on this post · TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: