Posts tagged with c - page 3

8 things you probably didn’t know about C#

Here’s a few unusual things about C# that few C# developers seem to know about.

1. Indexers can use params

We all know the regular indexer pattern x = something[“a”] and to implement it you write:

public string this[string key] {
  get { return internalDictionary[key]; }
}

But did you know that you can use params to allow x = something[“a”, “b”, “c”, “d”] ?

Simply write your indexer like this:

public IEnumerable<string> this[params string[] keys] {
  get { return keys.Select(key => internalDictionary[key]).AsEnumerable(); }
}

The cool thing is you can have both indexers in the same class side-by-side. If somebody passes an array or multiple args they get an IEnumerable back but call with a single arg and they get a single value.

2. Strings defined multiple times in your code are folded into one instance

Many developers believe that:

if (x == "" || x == "y") { }

will create a couple of strings every time. It won’t.

C#, like many languages, has string interning and every string your app compiles with gets put into an in-memory list that is referenced at run-time.

You can use String.Intern to see if it’s currently in this list but bear in mind that doing String.Intern(“what”) == “what” will always return true as you just defined another string in your source. String.IsInterned(“wh” + “at”) == “what” will also return true thanks to compiler optimizations. String.IsInterned(new string(new char[] { ‘w’,’h’,’a’,’t’ }) == new string(new char[] { ‘w’,’h’,’a’,’t’ }) will only return true if you have “what” elsewhere in your program or something else at run-time has added it to the intern pool.

If you have classes that build up or retrieve regularly used strings at run-time consider using String.Intern to add them to the pool. Bear in mind once in they’re there until your app quits so use String.Intern carefully. The syntax is simply String.Intern(someClass.ToString())

Another caveat is that doing (object)”Hi” == (object)”Hi” will return true in your app thanks to interning. Try it in your debug intermediate window and it will be false as the debugger will not be interning your strings.

3. Exposing types as a less capable type doesn’t prevent use as their real type

A great example of this is when internal lists are exposed as IEnumerable properties, e.g.

private readonly List<string> internalStrings = new List<string>();
public IEnumerable<string> AllStrings { get { return internalStrings; } }

You’d likely think nobody can modify internal strings. Alas, it’s all too easy:

((List<string>)x.AllStrings).Add("Hello");

Even AsEnumerable won’t help as that’s a LINQ method that does nothing :( You can use AsReadOnly which creates a wrapper over the list that throws when you try and set anything however and provides a good pattern for doing similar things with your own classes should you need to expose a subset of internal structures if unavoidable.

4. Variables in methods can be scoped with just braces

In Pascal you had to declare all the variables your function would use at the start of the function. Thankfully today the declarations can live next to their assignment and use which prevents accidentally using the variable before you intended to.

What it doesn’t do is stop you using it after you intended. Given that for/if/while/using etc. all allow a nested scope it should come as only mild surprise that you can declare variables within braces without a keyword to achieve the same result:

private void MultipleScopes() {
  { var a = 1; Console.WriteLine(a); }
  { var b = 2; Console.WriteLine(a); }
}

It’s almost useful as now the second copy-and-pasted code block doesn’t compile but a much better solution is to split your method into smaller ones using the extract method refactoring.

5. Enums can have extension methods

Extension methods provide a way to write methods for existing classes in a way other people on your team might actually discover and use. Given that enums are classes like any other it shouldn’t be too surprising that you can extend them, like:

enum Duration { Day, Week, Month };

static class DurationExtensions {
  public static DateTime From(this Duration duration, DateTime dateTime) {
    switch(duration) {
      case Day:   return dateTime.AddDays(1);
      case Week:  return dateTime.AddDays(7);
      case Month: return dateTime.AddMonths(1);
      default:    throw new ArgumentOutOfRangeException("duration");
    }
  }
}

I think enums are evil but at least this lets you centralize some of the switch/if handling and abstract them away a bit until you can do something better. Remember to check the values are in range too.

6. Order of static variable declaration in your source code matters

Some people insist that variables are ordered alphabetically and there are tools around that can reorder for you… however there is one scenario where reordering can break your app.

static class Program {
  private static int a = 5;
  private static int b = a;

  static void Main(string[] args) {
   Console.WriteLine(b);
  }
}

This will print the value 5. Reorder the a and b declarations and it will output **.

7. Private instance variables of a class can be accessed by other instances

You might think the following code wouldn’t work:

class KeepSecret {
  private int someSecret;
  public bool Equals(KeepSecret other) {
    return other.someSecret == someSecret;
  }
}

It’s easy to think of private as meaning only this instance of a class can access them but the reality is it means only this class can access it… including other instances of this class. It’s actually quite useful for some comparison methods.

8. The C# Language specification is already on your computer

Providing you have Visual Studio installed you can find it in your Visual Studio folder in your Program Files folder (x86 if on a 64-bit machine) within the VC#\Specifications folder. VS 2010 comes with the C# 5.0 document in Word format.

It’s full of many more interesting facts such as:

  • i = 1 is atomic (thread-safe) for an int but not long
  • You can & and nullable booleans with SQL compatibility
  • [Conditional("DEBUG")] is an alternative to #if DEBUG

And to those of you that say “I knew all/most of these!” I say “Where are you when I’m recruiting!” Seriously, it’s hard enough trying to find C# devs with a solid understanding of the well-know parts of the language.

[)amien

Enums – Better syntax, improved performance and TryParse in NET 3.5

Recently I needed to map external data into in-memory objects. In such scenarios the TryParse methods of Int and String are useful but where is Enum.TryParse? TryParse exists in .NET 4.0 but like a lot of people I’m on .NET 3.5.

A quick look at Enum left me scratching my head.

  • Why didn’t enums receive the generic love that collections received in .NET 2.0?
  • Why do I have to pass in typeof(MyEnum) everywhere?
  • Why do I have to the cast results back to MyEnum all the time?
  • Can I write TryParse and still make quick – i.e. without try/catch?

I found myself with a small class, Enum<T> that solved all these. I was surprised when I put it through some benchmarks that also showed the various methods were significantly faster when processing a lot of documents. Even my TryParse was quicker than that in .NET 4.0.

While there is some small memory overhead with the initial class (about 5KB for the first, a few KB per enum after) the performance benefits came as an additional bonus on top of the nicer syntax.

Before (System.Enum)

var getValues = Enum.GetValues(typeof(MyEnumbers)).OfType();
var parse = (MyEnumbers)Enum.Parse(typeof(MyEnumbers), "Seven");
var isDefined = Enum.IsDefined(typeof(MyEnumbers), 3);
var getName = Enum.GetName(typeof(MyEnumbers), MyEnumbers.Eight);
MyEnumbers tryParse;
Enum.TryParse<MyEnumbers>("Zero", out tryParse);

After (Enum)

var getValues = Enum<MyEnumbers>.GetValues();
var parse = Enum<MyEnumbers>.Parse("Seven");
var isDefined = Enum<MyEnumbers>.IsDefined(MyEnumbers.Eight);
var getName = Enum<MyEnumbers>.GetName(MyEnumbers.Eight);
MyEnumbers tryParse;
Enum<MyEnumbers>.TryParse("Zero", out tryParse);

I also added a useful ParseOrNull method that lets you either return null or default using the coalesce so you don’t have to mess around with out parameters, e.g.

MyEnumbers myValue = Enum<MyEnumbers>.ParseOrNull("Nine-teen") ?? MyEnumbers.Zero;

The class

GitHub has the latest version of EnumT.cs

Usage notes

  • This class as-is only works for Enum’s backed by an int (the default) although you could modify the class to use longs etc.
  • I doubt very much this class is of much use for flag enums
  • Casting from long can be done using the CastOrNull function instead of just putting (T)
  • GetName is actually much quicker than ToString on the Enum… (e.g. Enum.GetName(a) over a.ToString())
  • IsDefined doesn’t take an object like Enum and instead has three overloads which map to the actual types Enum.IsDefined can deal with and saves run-time lookup
  • Some of the method may not behave exactly like their Enum counterparts in terms of exception messages, nulls etc.

[)amien

LINQ to SQL tips and tricks #3

A few more interesting and lesser-known LINQ to SQL techniques.

Lazy loading with stored procedures

LINQ to SQL supports stored procedures for retrieving entities, insert, update and delete operations but you can also use them to perform lazy-loading of navigation properties.

Lets show an example of a bi-directional relationship between a Post and a Comment. We have two stored procedures shown below and we bring them into the DBML by dragging them from Server Explorer into the LINQ to SQL designer surface and we set the return type property for each to the expected entity (Post and Comment respectively).

CREATE PROCEDURE LoadPost (@PostID int) AS SELECT * FROM Posts WHERE ID = @PostID
CREATE PROCEDURE LoadComments(@PostID int) AS SELECT * FROM Comments WHERE Parent_Post_ID = @PostID

This generates two method stubs named LoadPost and LoadComments that we can use to programatically retrieve entities:

var post = dataContext.LoadPost(1).First();
Console.WriteLine("{0}", post.Title);

Now to replace LINQ to SQL’s lazy-loading query generation we add  methods to the data context subclass with a specific signature.

partial class DataClasses1DataContext {
  protected IEnumerable<Comment> LoadComments(Post post) {
    return this.LoadComments(post.ID);
  }

  protected Post LoadParentPost(Comment comment) {
    return this.LoadPost(comment.Post_ID).First();
  }
}

To get the signature of the method names right:

  1. Visibility can be anything (protected or private is recommended)
  2. Return type must be the type of the other side of the association (wrapped in IEnumerable when that side can be many)
  3. Method name must start with the word “Load”
  4. Method name must then continue with the name of the navigation property you want to intercept
  5. Parameter type must be the type that has the named navigation property (step 4)

Storing and retrieving binary files

LINQ to SQL supports the SQL Server’s varbinary type but storing something practical like a file in there isn’t so clear. Map your varbinary(max) column from your table into your entity which will expose the column as the special System.Data.Linq.Binary type (effectively a wrapper for a byte array but better change tracking).

File to database

To store a file in the database just read those bytes in and assign them to the property (Binary knows how to create itself from a byte array automatically). e.g.

var readPath = @"c:\test.jpg";
var storedFile = new StoredFile();
storedFile.Binary = File.ReadAllBytes(readPath);
storedFile.FileName = Path.GetFileName(readPath);
data.StoredFiles.InsertOnSubmit(storedFile);

I recommend storing the file name as well as the binary contents for two reasons. Firstly writing the file back to disk or streaming it to a browser will require you know the file type (e.g. .jpg or image/jpeg) and secondly nobody likes downloading a a file called ‘download’ or ‘1’ :)

Database to file

Writing the file back to disk is just as easy although you have to use the ToArray() method of System.Data.Linq.Binary to turn it back into a byte array.

var writePath = @"c:\temp";
var storedFile = data.StoredFiles.First();
File.WriteAllBytes(Path.Combine(writePath, storedFile.FileName), storedFile.Binary.ToArray());
Always ensure when writing to the file system based on data that your filenames are sanitized! You don’t want users overwriting important files on your system.

Multiple databases with a single context

Contrary to popular belief you can in fact access entities from multiple databases with a single data context providing they live on the same server. This isn’t supported but I’ve used it on my own projects without issue :)

The first part is the tricky bit which involves getting the definition of your entity into your DBML. You have two options here:

Create a temporary view

If you have the rights you can temporarily create views in your primary database for each table in your non-primary database.

CREATE VIEW MyOtherTable AS SELECT * FROM MyOtherDatabase.dbo.MyOtherTable

Once the views are created add them to your DBML by dragging them from Server Explorer into the LINQ to SQL designer surface and delete the views you created from the database.

Create a temporary DBML

If you can’t or don’t want to create temporary views then add a second (temporary) LINQ to SQL classes file (DBML) to your project. Use Server Explorer to find your secondary database and drag all the tables you will want to access to the LINQ to SQL designer surface.

Now save & close open files and use the right-mouse-button context menu to Open With… and choose XML Editor on your original DBML and the new temporary one. Head to the Window menu and select New Vertical Tab Group to make the next step easier.

Looking through the DBML you will see each entity has a <Table> block inside the . Select all the Table tags and their children (but not Database or Connection) and copy/paste them into your existing DBML file. Then close the files and check all looks well in the designer again.

If it does, delete the temporary DBML file you created. If not go back and check the DBML file for duplicate names, mismatched XML etc.

Finally, the easy bit

Open the designer and for each table that comes from the other database select it and change the Source property in the Properties window from dbo.MyOtherTable to MyOtherDatabase.dbo.MyOtherTable.

Hit play and run!

Check out part 1 of LINQ to SQL tips

[)amien

When an object-relational mapper is too much, DataReader too little

I fired up Visual Studio this evening to write a proof-of-concept app and found myself wanting strongly typed domain objects from a database but without the overhead of an object-relational mapper  (the application is read-only).

One solution is to write methods by hand, another is to code generate them but it would be nice to be able to do:

var customers = new SqlCommand("SELECT ID, Name FROM Customer", connection)
  .As(r => new Customer { CustomerID = r.GetInt32(0), Name = r.GetString(1) }).ToList();

So for any DbCommand object you can turn it into a bunch of classes by specifying the new pattern.

The tiny helper class to achieve this is:

public static class DataHelpers {
  public static List<T> ToList<T>(this IEnumerable<T> enumerable) {
    return new List<T>(enumerable);
  }

  public static IEnumerable<T> As<T>(this DbCommand command, Func<IDataRecord, T> map) {
    using (var reader = command.ExecuteReader())
      while (reader.Read())
        yield return map(reader);
  }
}

It might even be possible to do some cool caching/materialization. I should look into that :)

[)amien