LA.NET [EN]

CLRArchive

Jun 15

Getting started with attributes in .NET

Posted in .NET, Basics, C#, CLR       Comments Off on Getting started with attributes in .NET

We’ve already covered a lot of ground on the basics series…but guess what? There’s still a lot more to cover Smile Today, we’ll start looking at how we can improve our .NET code with attributes. With attributes, we can add custom metadata to our types (and/or a type’s members). After adding extra information to a type (or to a type’s member), you can then query it at runtime through reflection so that you can influence the way some piece of code is executed. Make no mistake about it: we’re talking about some very interesting stuff here! If you don’t believe me, then take a quick look around and you’ll notice  that several .NET technologies rely heavily on it (for instance, it’s used in Windows Forms, WCF, WPF, Siverlight, serialization – oh damn, serialization is also an interesting topic for future posts, don’t you think? – you name it!).

In .NET, anyone can reuse one of the predefined attributes or   just create new one for a specific scenario. Since attributes are targeted at the CLR, then all compatible compilers must understand them, interpret them and add the required entries to a type’s metadata. Before going on, it’s important to understand that most attributes have only one purpose: defining the metadata that will be associated with a type or member. And that’s it. To drive this point home, let’s take a look at the following code:

[Serializable]
public class Student {
    private String _name;

    public String Name {
        get { return _name; }
        set { _name = value; }
    }
}

The first thing you should notice in the previous snippet is that we apply an attribute to a type (or member) through the use of square brackets. In the previous snippet, we’re using the SerializableAttribute to say that Student type instances can be serialized. In C#, you can apply attributes to the assembly, module, types, fields, methods, method return values, properties, events and generic type parameters. Once again, from the previous example, it’s easy to understand that, by default, an attribute is applied to the associated type or member. There are, however, scenarios where you need to use a prefix to make it clear to what you’re applying an attribute to. The next snippet shows how to apply an attribute to an assembly:

[assembly: Guid("7a57294c-864f-44bd-b09e-eecc1ebef510")]

Besides assembly, you can also use the module prefix if you intend to annotate the module with a specific attribute and the return prefix if you want to make sure that an attribute is applied to the return value of a method. If you’re targeting the compiler generated field or methods of an event declaration, then you need to use the field and method prefixes:

[Serializable]
public class Student {
    private String _name;

    public String Name {
        get { return _name; }
        set { _name = value; }
    }

    [method: MyDummy]
    [field: MyDummy]
    public event EventHandler SomethingHappened;
}

MyDummy is a custom attribute (we’ll return to this topic in the future). Interestingly, these last two prefixes are optional when you’re targeting a method or a field:

[/*method:*/MyDummy]
public void DoIt() { }

Finally, there  are also the property and param prefixes which can be used to indicate that an attribute is being used to annotate a property or a parameter:

[property:MyDummy]
public String Name {
    //applied to method: no need to use method:
    [MyDummy]
    get { return _name; }
    set { _name = value; }
}
public void PrintIt([/*param:*/MyDummy]String info) { }

If you’re just starting, then you’ve probably noticed that the compiler allows us to cut the Attribute suffix from the attribute name. This is only possible because the C# compiler team thought that it would be a good idea to reduce the amount of typing and to improve the readability.

And that’s it for now. In the next post we’ll keep looking at attributes. Stay tuned for more.

May 12

In the previous post, we’ve started looking at encodings. In this post, we’ll finally put those theoretical concepts in practice and we’ll take a look at some code. Let’s start with a simple example. Suppose you’re building an application which will only handle English Strings. In this case, you know that UTF-8 will probably be a good option because it can use a single byte for representing all written chars. And that’s why you might decide to use it whenever you need to send or receive strings across the network:

var str = "This is a string which is going to be encoded";
var bytes = Encoding.UTF8.GetBytes( str );

 

Yes, it’s that easy! You start by getting a reference to an instance of an Encoding and then you encode an existing string into a byte array by calling its GetBytes method (the UTF8 static property returns an instance of the UTF8Encoding type, which extends the abstract Encoding type). If you only want to check out the number of bytes which are needed to encode a string, then you should resort to the GetByteCount method:

var str = "This is a string which is going to be encoded";
Console.WriteLine(Encoding.UTF8.GetByteCount( str ));

 

Calling the GetByteCount isn’t really a fast operation because the method analyzes all the chars in the string in order to return the correct number of bytes required. If you need to improve the performance of that call, then you can go with the GetMaxByteCount method. In this case, we end up with the number of bytes required for the worst case scenario (the method receives the number of chars in the string and multiplies it by the maximum number of bytes it needs to represent its “biggest” char):

var str = "This is a string which is going to be encoded";
Console.WriteLine(Encoding.UTF8.GetMaxByteCount( str.Length ));//138

 

Besides UTF8Encoding, the framework introduces several other specific Encoding implementations: ASCIIEncoding (encodes a string using the ASCII character set), UnicodeEncoding, UTF32Encoding (used for encoding each char as a 32 bit integer) and UTF7Encoding (encodes each char as a 7-bit sequence). You can create an instance of any of these encodings in two ways:

  1. you can instantiate them through constructor calls (not a good option in most scenarios).
  2. you can access an instance through one of the static properties of the Encoding class. btw, you should notice that Unicode and BigEndianUnicode return a reference to a UnicodeEncoding. The difference is that BigEndianUnicode returns a UnicodeEncoding which encodes chars in the big endian format.

The curious reader might also have noticed that the Encoding type offers a static Default property which also returns an Encoding object. This encoding is able to encode (or decode) by using the current user’s code page (as defined in the control panel’s regional settings applet). As I’ve said in the previous post, you can also use custom code pages (at your own risk!) encodings. To achieve that, you need to use the static GetEncoding method. There are several overloads which let you get a custom Encoding object by code page identifier or by code page name. The following snippet presents 3 different ways to get a handle to a UTF8Encoding instance:

var enc1 = Encoding.UTF8;
var enc2 = Encoding.GetEncoding( "utf-8" );
var enc3 = Encoding.GetEncoding( 65001 );
Console.WriteLine(enc1 == enc2);//true
Console.WriteLine(enc2 == enc3);//true

 

The previous example  also shows another interesting thing: each Encoding object is only created once when you get a reference from one of the Encoding type’s static methods or properties. So, whenever you request for an Encoding which has already been created, you end up receiving a reference to that previously created instance. Notice that this rule does not apply if you use the constructor of one of the existing derived Encoding types:

var enc1 = Encoding.UTF8;
var enc2 = new UTF8Encoding();
Console.WriteLine(enc1 == enc2);//false

 

If you look at the Encoding derived types constructor, you’ll notice that they offer several constructor overloads which allow you to fine tune the way encodings work. For instance, the UTF8Encoding introduces constructors which allows us to specify if  an encoding operation should generate a preamble (aka, BOM) and if an exception should be thrown when an invalid encoding is detected.

As you might have guessed, you can also recover a string from a previously encoded byte array. To perform a decoding, you need to 1.) get an instance of the appropriate Encoding and 2.) call its GetString method. Here’s how we can recover our previous encoded string:

var anotherString = Encoding.UTF8.GetString( bytes );
Console.WriteLine(anotherString);

So, decoding is not that hard either, right? If you’re interested in knowing how many chars will result from a decoding operation, then you should use the GetCharCount method:

Console.WriteLine( Encoding.UTF8.GetCharCount( bytes ));

 

Once again, it you’re interested in speed, then you can resort to the GetMaxCharCount method. Before ending, there’s still time mention that the Encoding type offers several properties which allow you to get info about it. For instance, you can access the CodePage property to get its code page identifier. There are other interesting properties, but I’ll redirect you to the docs since this becoming a rather large post.

That’s it for now. Stay tuned for more.

Mar 30

So, you know everything about text, right?– part II

Posted in Basics, C#, CLR       Comments Off on So, you know everything about text, right?– part II

In the previous post, we’ve started looking at how to work with text in C# and we’ve run a rather superficial analysis over the Char type. In this post, we’ll start looking at the String type which is probably what you’ll be using most of the time when you need to work with text.

What is a string? In .NET, a string can be seen as a an immutable sequence of characters. Programmatically,  it’s represented through the String type which is sealed and extends the Object type directly (in other words, it’s a reference type). Interestingly, Strings are also considered a primitive type in C# and this means that you can create new Strings through literals:

var aString = "Hello, there";

This is the preferred way to instantiate a new String. The type offers several constructors which let you create a new String from an unmanaged array of chars (char*) or from an unmanaged  array of 8-bit signed integers (aka, SByte). And no, there’s no constructor that receives a string as an argument, though there’s one which creates a new String from an array of Char.

Notice that using the preferred way of creating new strings (ie, through a literal) doesn’t really result in creating a “new“ instance through the newobj IL call. In these cases, the compiler embeds the string in the metadata so that it can load it at runtime.

Strings enjoy special treatment in several languages. For instance, it’s possible to concatenate strings at compile time or at runtime. Here’s an example where the C# compiler is smart enough to concatenate two Strings at compile time:

var aString = "Hello," +" there";

If you’ve had the luck to write some code in C or C++, then you’ll be right at home with the string escape sequences supported in C#:

var aString = "Hello,\tthere";

In the previous snippet, we’ve resorted to \t to introduce a tab in a string. In case you’re wondering, you can escape the \ char used in escape sequences by doubling it:

var path = "C:\\folder";

If you have lots of \ to escape, then you should be using verbatim strings:

var path = @"C:\folder";

Both snippets produce exactly the same results: you end up with a c:\folder string.

Before ending this initial post about strings, there’s one small detail I’ve mentioned at the beginning and which is *really* important. It’s probably the most important thing you should know about strings and I wouldn’t really feel well without writingabout it: strings are *immutable*. Once you create a string, there’s no way to modify it. No, you can’t change a char from it without building a new String instance. No, you can’t make it shorter or longer either!

This might be a surprise, but it does bring a couple of advantages too. For instance, since they’re immutable, you don’t have to worry about synchronization in multithreaded code (IMO, this is a big big thing!). So, you need to do a lot char manipulations? Probably need to concatenate lots of strings at runtime? If that is your case, then you should be using StringBuilder (we’ll be back to this in a future post).

And this is it for now. Stay tuned for more!

Mar 28

So, you know everything about text, right?– part I

Posted in Basics, C#, CLR       Comments Off on So, you know everything about text, right?– part I

In .NET, characters are always represented by 16 bits Unicode values. Programmatically, they’re represented through instances of the System.Char type. Here’s an example of a char represented in C#:

var myChar = 'a';

The Char type offers several helper static methods which do several useful operations. For instance, you can call the IsLetter method to check if a char is a letter:

var isLetter = Char.IsLetter('a');

Besides the IsLetter method, you can also use the IsDigit, IsWhiteSpace, IsUpper, IsLower, IsPuctuation, IsLetterOrDigit, IsControl, IsNumber, IsSeparator, IsSurrogate, IsLowSurrogate, IsHighSurrogate or IsSymbol methods. All these methods have overloads which receive a string and a position that points to the char that needs to be checked. You can get the same results by calling the GetUnicodeCategory method, which returns a value of the UnicodeCategory enumeration. According to the docs, you shouldn’t use this method but the CharUnicodeInfo.GetUnicodeCategory. A small detour: surrogates are an interesting (though out of the scope of this post). Basically, they’re needed to allow the representation of the supplementary characters outside the BMP (Basic Multilingual Plane) with UTF-16. If you’re interested in learning more, I’d recommend getting started here.

Besides checking the “kind” of a character, you can also convert it its lower or upper equivalent in a culture-agnostic way throw the ToLowerInvariant and ToUpperInvariant methods (if you want to take the culture into consideration, then you should call the ToLower and ToUpper methods).

The char type does offer some instance methods too (btw, the previous ones are all static), You can compare two chars through the Equals method or through the CompareTo method (because Char implements the IComparable<char> interface). Besides comparing, you can also find a couple of methods which let you transform a char (or chars) into strings or get chars from an existing string. There’s still another couple of methods which are capable of building chars out of one or more integers (which, as you might have guessed, represent code values). Finally, the GetNumericValue returns the numeric equivalent of the current char.

Before ending this post, there’s still time to refer that the CLR allows you to convert from char into a numeric type (and vice-versa). Explicit casts are the easiest way to do that. You can also perform this operation through one of the methods of the Convert type or by using the IConvertible interface (that is implemented by Char). And I guess this sums it up quite nicely. Stay tuned for more about text.

Mar 26

Last considerations about generics

Posted in Basics, C#, CLR       Comments Off on Last considerations about generics

As we’ve seen, constraints will help in writing “type safe generic code” (not sure if this designation really exists. if it doesn’t, then I’ve invented Smile). But even with generics, there are still a couple of scenarios which might caught you by surprise. Lets start with casts and with a simple example:

class Generic<T> {
    public void DoSomethin(T something) {
        var aux = (String) something;
    }
}

The previous class won’t compile because there’s no way for the compiler to know that it’s possible to convert something into a String. At least, not when it’s compiling the generic open class! Notice that you can’t even apply a constraint to solve this problem. There is, however, a workaround (which isn’t really type safe):

class Generic<T> {
    public void DoSomethin(T something) {
        var aux = (String)(Object) something;
    }
}

Since any object can be cast to Object, then the compiler won’t complain about that first cast. The other cast (String) is now possible, though it might throw an exception at runtime. In fact, there’s a better option of doing the previous cast:

class Generic<T> {
    public void DoSomethin(T something) {
        var aux = something as String;
    }
}

Notice, however, that you’ll only be able to do this whenever you’re converting something into a reference type.

Since generic type arguments can be replaced by any concrete type, then you might be wondering how can you initialize a “generic” variable to its default value. The problem here is specifying its default value. I mean, if you’re talking about reference types, then it’s ok to set it to null. However, doing it with a value type results in a compile type error. To solve this problem, Microsoft introduced the default keyword:

class Generic<T> {
    public void DoSomethin(T something) {
        T aux = default(T);
    }
}

Now, the compiler is happy. When T is replaced by a reference type, aux is initialized with null. On the other hand, if T is replaced by a value type, then aux reference some memory space (big enough to save a value of that type) with all its bits initialized to 0. Btw, there’s also an interesting gotcha regarding the use of null: you can’t use it to initialize a variable, but you can use it with the operators == and !=. Here’s and example:

class Generic<T> {
    public void DoSomethin(T something) {
        if(something == null ) {
            //do something
        }
        else {
            //do something else
        }
    }
}

When T is replaced by a value type, the JIT compiler won’t emit the native code for the if part because a value type never is null. Notice that if we had constrained T to a struct, then yes, we’d be getting a compile error on the if clause.

It’s also important to understand that comparing two variables of the same generic type results in an error if that generic type isn’t constrained to a reference type:

class Generic<T> {
    public void DoSomethin(T something, T somethingElse) {
        if( something == somethingElse) {
            //some code
        }
    }
}

If T were constrained to a reference type, the code would have compiled without any errors. However, constraining T to a a value type, will always result in an error. Since you cannot constrain T to a specific value type (a value type is always sealed and we’ve seen that we can’t do that because it’s more efficient to write code that uses directly that type), you’re limited to saying that it’s a value type. And this information isn’t enough to make the compiler do its work and emit the correct code for the comparison.

A final note: you can’t use generic type variables as operands (ie, you can’t use them with the operators +, –, *, etc.), making it impossible to write expressions which work for any numeric type. This is a tremendous problem, especially for those guys that work in the financial world…

And that’s it for now! Stay tuned for more.

Mar 23

Generic and constructor constraints

Posted in Basics, C#, CLR       Comments Off on Generic and constructor constraints

In this post, we’ll talk about one last kind of constraints: the constructor constraint. Whenever you apply a type constraint to a generic type argument, the compiler ensures that it can only be replaced by a concrete type which does expose a public default constructor. Constructor constrains are specified through the new keyword, as you can see from the following snippet:

public class AnotherGenericConstraint<T> where T:new() {
    public T GetNew() {
        return new T();
    }
}

Without constructor constraints, there really wouldn’t be a way for the compiler to allow you to instantiate generic type to which a primary constraint struct *hasn’t* been applied. Btw, and since we talk about value types, it’s an error to specify both a struct and type constraint to a generic type argument:

public class AnotherGenericConstraint<T>
    where T:struct, new() { //compile error
    public T GetNew() {
        return new T();
    }
}

A final note: currently, there’s not way to specify the number of parameters a constructor may receive. And it seems like that won’t change in the future, meaning that we’re struck with parameterless constructors. And I guess this is all about generic constraints. Stay tuned for more.

Mar 23

Generics and secondary constraints

Posted in Basics, C#, CLR       Comments Off on Generics and secondary constraints

Besides primary constraints, you can also constrain a generic type parameter through secondary constraints. Unlike primary constraints, you can apply zero or more secondary constraints to a generic type argument. Interfaces constraints are the most common kind of secondary constraints you’ll apply in your code. They allow the compiler to ensure that a generic type argument can only be replaced by a type which implements the interface specified by the constraint. If you want, you can specify several interface constraints. In these cases, you can only replace the generic type argument by a concrete type which implements all those interfaces. The next snippet illustrates the use of this kind of constraint:

public interface IDoSomething{}
public interface IDoSomethingElse{}
public class DoEverything:IDoSomething,IDoSomethingElse {
}
public class DoOneThing:IDoSomething {
}
public class MyGeneric<T> where T:IDoSomething, IDoSomethingElse {
        
}

And here’s some code that instantiates the class:

var aux1 = new MyGeneric<DoEverything>();//ok!
var aux2 = new MyGeneric<DoOneThing>();//oops

Besides interfaces, there’s another kind of secondary constraint, which is known as naked type constraint. This secondary constraint allows you to specify the existence of a relationship between two generic type arguments. Here’s a quick example:

public class AnotherGeneric<T, TBase> where T:TBase {
        
}

And here’s some code that shows how you can (and can’t instantiate it):

public class A{}
public class B:A{}
var ok = new AnotherGeneric<B, A>();
var oopss = new AnotherGeneric<A, B>();

ok compiles without an error, but that doesn’t happen with oopss because the compiler knows it can’t convert from A to B (though it knows that it can convert from B to A) .

And I guess that’s it for now. Stay tuned for more.

Mar 21

Generics and primary constraints

Posted in Basics, C#, CLR       Comments Off on Generics and primary constraints

In the previous post, we’ve started looking at constraints. Primary constraints are one type of constraints. Currently, you can specify zero or one primary constraint when you introduce a generic type argument. Whenever you restrain a generic type argument to a non-sealed class, you’re using a type constraint. Here’s an example:

public class Test {
}
public class TestingConstraints<T> where T:Test {
}

When the compiler finds a primary constraint of this type, it knows that T can only be replaced by Test or from another type derived from Test. In the previous example, this means that all public members introduced by Test can be used from within the members of TestingConstraints. Btw, you can’t use a sealed type as a primary constraint. And it’s kind of logical, if you think about it. Lets suppose S is sealed. If S is sealed, then you can’t extend it (ie, you cannot create new derived types from it). That being the case, and if primary constraints could reference sealed types, then you’d be building a generic type whose type argument could only be replaced by *one* specific type. Well, we don’t really need generics to do that, right? I mean, the final result would be the same as creating a non-generic type which would reference directly the sealed type S! In other words, the generic type would end up being non-generic and that just doesn’t make sense!

Primary constraints are mandatory when introducing a generic argument. If you don’t specify one, then Object is used by default. Notice that the following types cannot be used as a primary constraint: Object, Array, Delegate, MulticastDelegate, ValuType, Enum and Void.

Besides referencing a non-sealed type, there are also two other special primary constraints: class and struct. When the compiler finds the class constraint, it knows that the generic type argument will only be replaced by a reference type. In practice, this means that the  generic type argument can be replaced by any class, interface, delegate or array type. On the other hand, when the compiler finds the struct constraint, it understands that the generic type argument will be replaced by a value type. In this case, the generic type argument can be replaced by any value or enum type.

There are some important assumptions the compiler can make from these special primary constraints. Here’s a small example:

public class GenericValueType<T> where T:struct {
    public T Create() {
        return new T( );
    }
}
public class GenericReferenceType<T> where T: class {
    public T DoSomething() {
        T aux = null;
        //some code
        return aux;
    }
}

The previous code compiles without an error. Whenever we constrain a generic type argument to a struct, then the compiler knows that it newing up T is ok because all value types have a default public constructor (and that might not happen with reference types). If you concentrate on GenericReferenceType, then you’ll notice that aux is initialized with the null value. You can only attribute null to reference type variables. Since you’ve constrained T to class, then the compiler knows that this assignment is doable and won’t complain about it (try removing the constraint and see what happens – there is a way to go around it, but I’ll leave it for a future post).

Notice that there’s a small gotcha regarding primary constraints associated with the struct keyword: you cannot replace the generic type argument with the Nullable<T> type. Nullable<T> is a value type (ie, struct), but it gets special treatment from the compiler and the CLR. It’s because of that you cannot replace T with Nullable<T> on GenericValueType<T>. Nullable<T> are an interesting topic and we’ll return to them in future posts.

And I guess this sums it up for primary constraints. In the next post, we’ll go over secondary constraints. Stay tuned for more.

Mar 21

Generics: getting started with constraints

Posted in Basics, C#, CLR       Comments Off on Generics: getting started with constraints

Now that we have basic knowledge about generics, we can proceed and talk about constraints. When we write “generic” code, the compiler must ensure that that code will work for any type which might be used in place of the generic type argument. For instance, take a look at the following code:

public class Test {
    void PrintInfo<T>(T genericObject) {
        Console.WriteLine(genericObject.ToString(  ));
    }
}

How can the compiler guarantee that the previous code will work for any type? (btw, lets ignore the fact that genericObject might be null). In the previous snippet, it’s really easy because we know that Object is the base class of all objects and ToString is one of the methods which is introduced by it. And what if we had the following code:

public class Test {
    void PrintInfo<T>(T first, T second)  {
        //compare both
        var comparison = first.CompareTo( second );
        if( comparison > 0 ) {
            Console.WriteLine("second smaller than first");
        }
        else if( comparison < 0 ){
            Console.WriteLine("first smaller than second");
        }
        else {
            Console.WriteLine("Equals");
        }
    }
}

The idea behind the previous snippet is simple: we’re expecting that T implements the IComparable<T> interface. If that happens, then we can call the CompareTo method over the first instance in order to compare them. As you’ve no doubt have noticed from the previous snippet, the compiler isn’t really happy with the CompareTo call. After all, implementing the IComparable<T> interface is really optional and the compiler can’t really generate IL code from the previous method that works for any type.

And that’s why we have constraints. With constraints, we can limit the number of types that can be specified for a generic type argument. By adding a constraint, we can make sure that the generic type argument will only be replaced by types which fall under certain conditions. So, lets fix the previous snippet so that it compiles:

public class Test {
    void PrintInfo<T>(T first, T second) where T:IComparable<T> {
        //compare both
        var comparison = first.CompareTo( second );
        if( comparison > 0 ) {
            Console.WriteLine("second smaller than first");
        }
        else if( comparison < 0 ){
            Console.WriteLine("first smaller than second");
        }
        else {
            Console.WriteLine("Equals");
        }
    }
}

A constraint is always specified through the where keyword and, in the previous example, it tells the compiler that T can only be replaced by a type which implements the IComparable<T> interface (trying to pass a type which doesn’t implement that interface results in a compiler error). With this small change, we can treat T like an object which implements IComparable<T>. Notice that constraints can be applied where you’re allowed to introduce generic types (ie, you can add constraints at class, interface, delegate or method level).

There are several types of constraints, which are grouped into several categories. In the next post, we’ll take a look primary constraints. Stay tuned for more.

Mar 20

As we’ve seen, we can define generics in interfaces, classes, delegates and methods. In a previous post, I’ve already mentioned that you cannot define generics for properties. Besides properties, you can’t also define generics  for indexers (aka parameterful properties), events, operators, constructors and finalizers. Notice that these members can use eventual generic type parameters defined at interface or class level, but they cannot introduce their own generic type parameters. Here’s an example of what you can’t do:

public class Test {
public Test<T>( ) {
}
}

You might be curious to understand why you cannot define generics for these members. I was curious too…the best answer I got pointed to two interesting facts:

  • it seems like there aren’t really many cases where this feature would be needed.
  • allowing it would mean that the languages would have to be redesigned to allow these features.

The best example for understanding this last point relies in understanding how operators are used. For instance,there’s currently no way to specify a generic type with an operator. Lets walk through a simple example:

var str1 = “Hello, “;
var str2 = “there!”;
var str3 = str1 + str2;

We’re adding two strings through the operator+. Suppose we could use generics when defining the operator+. How would we write the code for specifying the generic type? I mean, would this be a good option?

var str1 = “Hello, “;
var str2 = 1;
var str3 = str1 +<Int32> str2;

In my opinion, that wouldn’t really contribute to improve the readability of the code…and that’s it for now. Stay tune for more.

Mar 19

Generic interfaces and delegates

Posted in Basics, C#, CLR       Comments Off on Generic interfaces and delegates

In the previous post, I’ve introduced the concept of generics. In this post, we’ll keep looking at generics and we’ll talk a little bit about how we can create generic interfaces and delegates. Without generic interfaces, manipulating a value type through its interface reference would result in boxing (and less compile type safety). The some goes for delegates: with generics, it’s possible to create a delegate which allows a value type instannce to be passed back to a callback method in a type-safe way without any boxing.

There’s not much to say about the syntax used for creating generic interfaces and delegates. So, here’s an of a generic interface:

public interface IDoSomething<T> {
    void DoItNow(T);
    T Whatgetdate();
}

And here’s an example of a generic delegate (btw, it’s defined by the framework):

public delegate void Action<T>(T item);

Tipically, the compiler will transform a delegate into a class which looks like this:

public class Action<T> : MulticastDelegate {
    public Action(Object obj, IntPtr method);
    public virtual void Invoke(T item);
    public virtual IAsyncResult BeginInvoke(T item, AsyncCallback cb, Object obj);
    public virtual void EndInvoke(IAsyncResult result);
}

(And we’ll see why in future posts Smile)

From .NET 4.0 onward, the type arguments of a generic delegate or interface can be classified as contravariant or covariant. In previous versions, generic arguments were always invariant, ie, the generic type parameter couldn’t be changed after being defined. In C#, contravariant type arguments are indicated through the in keyword. It means that the generic type parameter can change from a class to another derived from it. On the other hand, covariant type arguments are indicated in C# through the out keyword and, in this  case, a generic type argument can change from a class to one of its  base class. An example might help you understand what’s goin here. Suppose we start with this (again, defined by the framework):

public delegate TResult Func<in T, out TResult>(T arg);

In this case, T is contravariant and TResult is covariant. So, if you have the following classes:

class Base {}
class Derived : Base {}

Now,  if you still haven’t forgotten that Object is the base class of all objects, then from .NET 4.0 onward, you can simply do this:

Func<Object, Derived> fun1 = null;//not important here
Func<Base, Base> fun2 = fun1;

Notice that there’s no cast there! this is not the easiest example to understand what’s going on, but I really don’t have time for more (sorry). What matters is understanding that fun1 references a method which expects and object and returns na instance of Derived. On the other hand, fun2 expects a method that receives a Base and returns another Base instance. Since you can  pass a Base to a method which expects an Object and since you can treat a Derived instance as  if it was a Base instance (because Derived extends Base), then the previous code is safe.

Interestingly, the compiler will only be happy with contravariance and covariance if it can infer that there is a conversion between the tpyes being used. That means that variance won’t work for value types because it would require boxing. In practice, this means that this won’t compile:

void DoSomething(IEnumerable<Object> items) { }
DoSomething(new List<Int32>());//ooops:  compiler error

It’s a pity, but that’s just the way it is. Before ending, there’s still time to say that you should always specify the variance of a type argument when creating generic arguments. This doesn’t introduce any nasty side effects and enables the use of the delegate in more scenarios. If you want to know more about variance, then I recommend reading Eric Lippert’s excellent series on the topic. And that’s it for now. Stay tuned for more.

Mar 14

Generics: open vs closed types

Posted in Basics, C#, CLR       Comments Off on Generics: open vs closed types

Before going on, does anyone know how to improve the performance of Windows Live Writer? It’s painfully slow after I’ve updated it to the latest release and it’s upsetting me a lot. I’ve tried to disable everything, but the damn app doesn’t show any improvements…damn…ok, enough bitching…

In the previous post, I’ve introduced generics. In this post, we’ll keep looking at generics and I’ll present the concept of open vs. closed type. Before going on, let’s recover the MyList snippet I’ve introduced in the previous post:

class MyList<T> {
    public void Add(T item) {
    }
    public void Remove(T item) {
    }
    public void Sort(IComparer<T> comparer) { }
}

And then there was some code which used MyList with ints:

var intList = new MyList<Int32>();
intList.Add(10);
intList.Remove(20);

And now, we’re ready to proceed Smile

As you probably know,the CLR uses internal data structures for every type used by an application. These data types are generally known as type objects. Generics are also types and that’s why it shouldn’t surprise you to find out that they too have their own type objects. In other worlds,MyList<T>  is a type and you can get its type object. However, there’s an important difference between MyList<T> and, say, String: you cannot instantiate a generic type without specifying a data type for its type parameter. That’s why we had to pass Int32  when we instantiated MyList in the previous snippet.

Btw, a type with generic type parameters is called an open type. Whenever code  references a generic type and replaces its generic type argument with a specific type, we end up with what is known as a closed type (notice that closed types are only obtained when all generic type arguments are replaced with concrete types; if that doesn’t happen, then you’re just creating a new open type). An interesting way to see the difference between open and closed types is to print the information returned by the typeof operator to the console:

Console.WriteLine(typeof(MyList<Int32>));
Console.WriteLine(typeof(MyList<>));

The previous snippet ends up printing the following:

ConsoleApplication1.MyList1[System.Int32]
ConsoleApplication1.MyList1[T]

The astute reader will probably notice the backtick followed by a number…the number represents the type’s arity, which is used for indicating the number of type parameters of that type. In our example, MyList arity 1 because it only has one type argument. Another interesting conclusion is that the closed type will share eventual static fields with all instances of that closed type (in our case, it MyList<T> introduced a static field, then MyList<Int32> is a closed type with its own static fields which aren’t shared with, say, MyList<String>).

Being a type, it’s also possible to use a generic type (open or closed) as a base type or to build a new generic type which extends an existing type. Before ending, time for one last gotcha: I’ve noticed that some developers prefer to do this:

class IntList : MyList<Int32> { }

instead of instantiating MyList<Int32> directly like I did in the previous snippets. Please, don’t do this. The problem with this approach is that IntList is a different type from MyList<Int32>:

Console.WriteLine(typeof(IntList) == typeof(MyList<Int32>));

The previous snippet prints false because we’re talking about types with different identities! If you prefer the last approach because it saves a few keystrokes, then don’t forget that you can use the var approach or even create an alias through the using keyword. And that’s it for now. Stay tuned for more.

Mar 14

Getting started with generics

Posted in Basics, C#, CLR       Comments Off on Getting started with generics

With generics, the CLR offers us another way to ensure code reuse. If you’re a C++ developer, you might be tempted to see generics as some sort of C++ templates. Even though there are certain similarities, the truth is that there are several important differences. For instance, in C++ the source code must be available for the developer instantiating the template. That is not the case with generics in .NET (there are other differences, many captured here). Before going on, I believe it’s a good time to show some code. When generics were introduced, they solved a really bad problem: how to encapsulate an algorithm and make it generic and type safe at the same time. The best way to understand it is to look at a quick example:

class MyList<T> {
    public void Add(T item) {
    }
    public void Remove(T item) {
    }
    public void Sort(IComparer<T> comparer) { }
}

In the previous snippet, MyList is a class which works with any data type (notice the <T> right after the class definition). T is called a type parameter and you can see  it as a name which can  be used anywhere a data type  is supposed to be used. Since the type parameter was introduced by the class itself (notice that  <T> is declared right after the class’ name), it can be used for fields,method’s parameter and return values. You can even used it as local variables from within the class’ methods. After creating a generic type,you can redistribute it and let other developers reuse it with a concrete type. For instance, here’s how you can reuse the previous class for storing lists of integers:

var intList = new MyList<Int32>();
intList.Add(10);
intList.Remove(20);

If you’ve tried to pass a string to intList’s Add method, you’d get a compile error. So, in .NET, generics are type safe because the compiler will always ensure that only objects compatible with the used data type parameter can be used where objects of that type are expected. If you’ve only started using .NET in the last years, then you probably haven’t noticed the performance improvement gained through its introduction. Before generics, generalized algorithms resorted to the Object type. Unfortunately, that meant that using those classes with value types would always result in boxing operations. This was really bad and you’d also need to use lots of casts to access the values  or objects saved by those classes. Thank god we’ve got generics!

Currently, the framework introduces several utility classes built with generics. For instance, the System.Collections.Generic, System.Collections.Object and System.Collections.Concurrent namespaces introduce several generic collection classes which should always be used whenever you need to work with collections and lists of elements. And yes, nothing prevents you from creating your own generic types. Currently, you can create generic reference and value types, but you cannot create generic enumerated types. Notice that you can even create generic interfaces, delegate and methods (useful for those cases where only the method encapsulates a reusable algorithm). Creating a generic is an interesting process, but we’ll leave that analysis for the next post.  Stay tuned.

Feb 28

Generic properties: you can’t do that!

Posted in Basics, C#, CLR       Comments Off on Generic properties: you can’t do that!

One of the things some people expect to be able to do is create generic properties. After all, properties will always generate getter and setter methods and nothing prevents you from creating generic methods. So why can’t I do something like this:

class Test{
    public T MyProp<T>{get;set;}
}

Well, it’s really a conceptual problem, you see…in theory, a property represents a characteristic of an object. Making it generic would mean that that characteristic would be able to change, but this really doesn’t play well with the theory, right? Anyway, what this means is that if you need to add some generic behavior into a class, then you  should do that by adding methods. Btw, don’t confuse the previous code with reusing the generic parameter defined by a class:

//compiles as expected :)
class Test<T>{
    public T MyProp{get;set;}   
}

In these last post, we’ve created a new generic type (we’ll come back to generics in the next posts)…notice that the type of the property isn’t  able to change after we create a new instance of a concrete type:

var test = new Test<Int32>();
test.MyProp = 10; //always int

I guess it’s time to say something about properties…to be honest, I really don’t like them. They look like fields, but they are methods. This means that some of the assumptions you end up doing when accessing fields aren’t true with properties. For instance, a field is always read/write (that might not happen with a property). Besides that, a property cannot be passed as a ref or out parameter and accessing one might also cause side effects (something which never happens with fields).

Over the years, I’ve seen them been abused by developers…hell, I’ve even abused them myself! Currently, I tend to stay away from them. In my opinion, people using them will end up with what is known as an anemic models (models in which there’s almost no behavior…). Currently, I only use properties in messages and for objects which are supposed  to feed UI forms (since the data binding process only works with them).

And that’s it for now. Stay tuned for more.

Nov 16

It seems like CLR 4.0 will introduce a new security model (which looks a lot like the one we’ve got in Silverlight). Shawn Farkas has an excellent post which compares the two rule sets and explains what happens in several scenarios.