C#: A Review on Generics

I think a good C# developer needs to get a handle on .NET generics.  Most of the advanced features in C# deal with lots of generics and having a very good understanding of generics will help considerably, most especially when dealing with generic delegates.  So here in this post, we will review generics.

Generic type definitions can be methods, classes, structures, and interfaces.

// an example generic class
public class MyGenericClass<T>
{
    public T MyProperty;
}

 

 

The placeholders (e.g. <T>) are called generic type parameters, or type parameters.

You specify the actual types to substitute for the type parameters during instantiation.

// instantiate generic class with string type
MyGenericClass<string> c = new MyGenericClass<string>();

 

 

When instantiated, a generic type definition becomes a constructed generic type.

You can place limits or constraints on generic type parameters.

// limit type to value types except Nullable
public class MyGenericClass<T> where T : struct {/*...*/}
    
// limit type to reference types which can include classes,
//  interfaces, delegates, and array types
public class MyGenericClass<T> where T : class {/*...*/}
    
// limit type to types with public parameterless constructor
// must be specified last in multiple constraints
public class MyGenericClass<T> where T : new() {/*...*/}
    
// limit type to specified base class or to types derived from it
public class MyGenericClass<T> where T : MyBaseClass {/*...*/}
    
// limit type to specified interface or to types that implement it
public class MyGenericClass<T> where T : IMyInterface {/*...*/}
    
    
// limit type to specified type parameter    
    
// in a generic member function, it limits its type to the type 
//  parameter of the containing type
public class MyGenericClass<T>
{
    void MyMethod<U>(List<U> items) where U : T {/*...*/}
}
    
// in a generic class, it enforces an inheritance relationship
//  between the two type parameters
public class MyGenericClass<T, U> where U : T {/*...*/}
    
    
// type parameter can have multiple constraints 
//  and constraints can also be generics
//  and constraints can be applied to multiple type parameters
public class MyGenericClass<T, U> 
    where T : MyClass, IMyInterface, System.IComparable<T>, new()
    where U : struct
{
    // ...
}

 

 

A method is considered a generic method definition if it has two parameter lists: a list of type parameters enclosed in <> and a list of formal parameters enclosed in ().  A method belonging to a generic or non-generic type does not make the method generic or non-generic.  Only the existence of the two parameter lists will make the method generic, as in the example below.

public class MyClass
{
    // a generic method inside a non-generic class
    T MyGenericMethod<T>(T arg) {/*...*/}
}

 

 

A type nested in a generic type is considered by CLR to be generic even if it doesn’t have generic type parameters of its own.  When you instantiate a nested type, you need to specify the type arguments for all enclosing generic types.

// generic type
public class MyGenericType<T, U>
{
    // nested type
    public class MyNestedType
    {
        // ...
    }
}
    
// ... somewhere in code you instantiate the nested type   
MyGenericType<string, int>.MyNestedType nt = 
    new MyGenericType<string, int>.MyNestedType();

 

 

The following are some common generic collection counterparts provided by the .NET framework:

 

There are also generic interface counterparts for ordering and equality comparisons and for shared collection functionality:

  • System.IComparable<T> and System.IEquatable<T> which define methods for ordering comparisons and equality comparisons.
  • IComparer<T> and IEqualityComparer<T> in the System.Collections.Generic namespace, which offer alternative way for types that do not implement System.IComparable<T> and System.IEquatable<T>.  They are used by methods and constructors of many of the generic collection classes.  An example would be passing a generic IComparer<T> object to the constructor of SortedDictionary<TKey, TValue> to specify a sort order.  Generic classes Comparer<T> and EqualityComparer<T> are their base class implementations.
  • ICollection<T> which provides basic functionality for adding, removing, copying, and enumerating elements in a generic collection type.  It inherits from IEnumerable<T> and the nongeneric IEnumerable.
  • IList<T> which extends ICollection<T> with methods for indexed retrieval.
  • IDictionary<TKey, TValue> which extends ICollection<T> with methods for keyed retrieval.  Generic dictionary types also inherit from nongeneric IDictionary.
  • IEnumerable<T> which provides a generic enumerator structure used by foreach.  It inherits from nongeneric IEnumerator because MoveNext and Reset methods appear only on the nongeneric interface.  This means consumer of the nongeneric interface can also consume the generic interface because the generic interface provides for nongeneric implementation.

 

You also have generic delegates in .NET framework.  An example is the EventHandler<TEventArgs> which you can use in handling events with custom event arguments.  No need to declare your own delegate type for the event.  If you need to brush up on events and delegates, see my post on raising events and nongeneric delegates.

public event EventHandler<PublishedEventArgs> Published;

 

 

There are also a bunch of useful generic delegates available for manipulating arrays and lists

  • Action<T> which allows you to perform action on an element by passing an Action<T> delegate instance and an array to the generic method Array.ForEach<T>.  You can also pass an Action<T> delegate instance to the nongeneric method List<T>.ForEach.
  • Predicate<T> which allows you to specify a search criteria to Array’s Exists<T>, Find<T>, FindAll<T>, and so on and also to List<T>’s Exists, Find, FindAll, and so on.
  • Comparsion<T> which allows you to provide a sort order.
  • Converter<TInput, TOutput> which allows you to convert between two types of arrays or lists.

 

Ok so that’s all we have for generics.  Just a review of the basics that a C# developer need to know.

Advertisements

C#: Quick Review on Raising Events

To illustrate raising events, let’s pick a very simple but classic example of a publisher and subscriber relationship.  Note that events make use of delegates and if you need to brush up on delegates, check my post here.

// So here you have a publisher class
public class Publisher
{
    // Inside you declare a public event
    // And the delegate type for the event is EventHandler
    public event EventHandler Published;
    
    // The event needs to be public to allow public subscription
    //  (e.g. p.Published += Subscriber1)
    // Also one might ask why we need the event keyword when, without it,
    //  making it a delegate, it basically does the same thing
    // Well, declaring an event lets you raise the event privately, but
    //  still allow public subscription
    // With a public delegate, anyone can remove other people's event
    //  handlers, raise the events themselves, etc. - an encapsulation
    //  disaster
    // Also when it's declared an event, it will appear in the list
    //  of properties with a lightning icon beside it
    
    // So EventHandler is a delegate type that accepts an object and an 
    //  EventArgs parameters and returns void
    // You can code the following instead and it will do the same thing
    public delegate void PublishedEventHandler(object sender, EventArgs e);
    public event PublishedEventHandler Published;
    
    // You can actually use a different event parameter if you prefer, 
    //  but that will mean not following the standard event handling
    public delegate void PublishedEventHandler(string title);
    public event PublishedEventHandler Published;
    
    // Also, using EventArgs for your event handler means you can't pass
    //  any event data to your event handler
    // If you need to pass data, you can use any event data type (like a
    //  string in the example above) or class.
    // Standard practice is to use an event data class derived from
    //  EventArgs and this will also require you to define a custom event
    //  handler delegate type
    public class PublishedEventArgs : EventArgs
    {
        public string Title { get; set; }
    }
    public delegate void PublishedEventHandler(object sender, 
                                                PublishedEventArgs e);
    public event PublishedEventHandler Published;
    
    
    // Next, you raise the event with the following method
    // The method needs to be protected and virtual so that any derived
    //  classes can override it if necessary
    protected virtual void OnPublished(EventHandler e)
    {
        EventHandler handler = Published;
        if (handler != null)
        {
            // Here we are calling the delegate which in turn invokes all
            //  the methods in it's invocation list (if there is more than
            //  one method to invoke)
            handler(this, e);
        }
    }    
    
    // Then the following public method just provides the publisher a
    //  means to notify it's subsribers of a newly published title
    public void Publish()
    {
        OnPublished(null);
    }

    // But if you are passing event data...
    protected virtual void OnPublished(PublishedEventArgs e)
    {
        PublishedEventHandler handler = Published;
        if (handler != null)
        {
            handler(this, e);
        }
    }
    
    public void Publish()
    {
        PublishedEventArgs e = new PublishedEventArgs();
        e.Title = "Hello World!!!";
        OnPublished(e);
    }    
}
    
    
// Somewhere in code outside the Publisher class, you have the following 
//  subscribers or event handlers
static void Subscriber1(object sender, EventArgs e)
{
    Console.WriteLine("Subscriber1 notified of new title");
}
    
static void Subscriber2(object sender, EventArgs e)
{
    Console.WriteLine("Subscriber2 notified of new title");
}
    
// Again, if you are passing event data...
static void Subscriber1(object sender, PublishedEventArgs e)
{
    Console.WriteLine("Subscriber1 notified of new title " + e.Title);
}
    
// Lastly, here you instantiate a publisher,
//  add the following subscribers,
//  and then publish a new title
Publisher p = new Publisher();
p.Published += Subscriber1;
p.Published += Subscriber2;
p.Publish();

 

C#: Quick Review on Delegates

A delegate is a type, much like the C/C++ function pointer, that can reference or encapsulate any method with the same method signature as the delegate.

Declaring a delegate is like declaring a regular method but without the method body and using the delegate keyword.

// declaring a delegate that accepts string as input and returns void
public delegate void MyDelegate(string msg);
    
// declaring a method with similar method signature as the delegate
public static void MyDelegateMethod(string msg)
{
    Console.WriteLine(msg);
}
    
// instantiating the delegate
MyDelegate d = MyDelegateMethod;
    
// calling the delegate
d("Hello Delegate!!!");

 

 

The instantiated delegate is an object, and as such can be passed as a parameter or assigned to a property.

// here is a method accepting a delegate as a parameter
// the delegate parameter is often called the callback method
public static void PassMeTheDelegate(MyDelegate callBack)
{
    callBack("Passed as a parameter");
}
    
// passing the instantiated delegate as a parameter to another method
// basically passing a callback method to another method
PassMeTheDelegate(d);
    
// assigning the instantiated delegate to another variable
MyDelegate v = d;
v("Assigned to a variable");

 

 

A delegate can call more than one method when invoked and this is referred to as multicasting, a feature extensively used in event handling.

// instantiate another delegate,
//  encapsulating another method with same method signature
MyDelegate e = MyDelegateMethod2;
    
// to multicast, add the delegates using the addition operator
MyDelegate multiCast = d + e;
    
// invoking a multicast delegate will invoke 
//  each of the delegate methods in the invocation list
multiCast("I am multicasting!");
    
// and you can also remove a method from the invocation list
multiCast -= d;
multiCast("Now I am not");

 

 

Because delegates are derived from System.Delegate, you can call the methods and properties defined by that class on the delegate.  Multicast delegates or delegates with more than one method in their invocation list derive from MulticastDelegate, which is a subclass of System.Delegate.

So far we have instantiated a delegate using a named method, where the method is defined elsewhere.  Another way of instantiating a delegate is with anonymous methods and lambda expressions, both are forms of inline code that you can pass as parameter or assign to property in place of a named method, except that lambda expressions are more concise.  Check out my post here on anonymous methods and lambda expressions.

Using CSS Media Queries

UsingMediaQueries2CSS media queries allows your site to be responsive by changing the styles and layout when viewed from different devices such as mobile devices.

Before media queries, web developers resort to creating a separate web site for mobile viewing.  With media queries you don’t have to anymore.  So what do media queries look like and how do you use them?

Media queries extend the existing media types, such as the screen and print, that HTML4 and CSS2 supports.

<link rel="stylesheet" type="text/css" media="screen" href="screen.css">

 

 

It queries the media type for  conditions, capabilities or features.  In the example below it asks the screen if it is in portrait orientation, and if it is, asks it to load the stylesheet portrait-screen.css.

<link rel="stylesheet" media="screen and (orientation: portrait)" 
href="portrait-screen.css" />

 

 

But the best way to use media queries is within CSS stylesheets using @media.

@media screen and (max-device-width: 400px) {
    h1 { color: green }
}

 

 

CSS @import can also be used to conditionally load stylesheets, but, just like the <link> tag, it adds to HTTP requests.

@import url("360maxwidth-screen.css") screen and (max-width: 360px);

 

 

The most commonly used media features are width, which is the device’s viewport width, and device-width, which is the device’s screen width.  And you can prefix min and max to almost all of the media features to define a range (e.g. min-width and  max-width).

Below is the formal syntax definition of media queries:

media_query_list: <media_query> [, <media_query> ]*
media_query: [[only | not]? <media_type> [ and <expression> ]*]
  | <expression> [ and <expression> ]*
expression: ( <media_feature> [: <value>]? )
media_type: all | aural | braille | handheld | print |
  projection | screen | tty | tv | embossed
media_feature: width | min-width | max-width
  | height | min-height | max-height
  | device-width | min-device-width | max-device-width
  | device-height | min-device-height | max-device-height
  | aspect-ratio | min-aspect-ratio | max-aspect-ratio
  | device-aspect-ratio | min-device-aspect-ratio | max-device-aspect-ratio
  | color | min-color | max-color
  | color-index | min-color-index | max-color-index
  | monochrome | min-monochrome | max-monochrome
  | resolution | min-resolution | max-resolution
  | scan | grid

 

CSS media queries from Mozilla Developer Network lists all the media features available with examples and also explains the formal syntax definition.

To illustrate the benefits of using media queries, open this page http://rodansotto.com/projects/css/fixedwidth.html in your choice of browser.  It is a classic example of a web page using the 960 grid system, which by the way, is a popular fixed grid layout system used by web designers for years.  It has 960px total width, 10px left and right margin, and 940px total content area.  If you continually resize your browser to decrease the width, it will just continue clipping the content.  If you view it on a mobile device, it will show the whole page but scaled down.  If it shows the page at 100 percent, still the content is clipped.

If I want the page to display nicely, say on a Nexus 7 tablet with 800 width resolution and a Nexus S smartphone with 480 width resolution, I need to add the following media queries to my CSS.

/* Nexus 7 tablet styles/layout */
@media screen and (max-width: 604px) {
}
/* Nexus S smartphone styles/layout */    
@media screen and (max-width: 320px) {
    /* ... */
}

 

Notice that the above media queries target a screen width of 604px for Nexus 7 instead of 800px.  This is because the ratio between the pixels you know, which is device-independent pixels, and the Nexus 7 device’s pixels is not 1:1 but 1.325:1.  For Nexus S it’s 1.5:1.

http://rodansotto.com/projects/css/usingmediaqueries.html displays the same page but using media queries so you can view the site nicely on a Nexus 7 and Nexus S devices.  If you don’t have any of these devices, you can resize your browser to decrease the width and notice how the page changes it’s layout at 604px and at 320px browser width.  You can view the HTML code from your browser when you right-click and select View page source or View source.  For CSS code, just use the same URL but with .css as the file extension instead of .html.

In conclusion, it’s nice and all having media queries available to make sure your site is displayed nicely on mobile devices.  But this is just a step in the right direction towards having a responsive web design.  Media queries can only get you as far as changing the styles and layouts for specific widths or viewports and anything in between you will still have the problem with content being clipped.  And this is where fluid layout comes in, which will be covered on the next post.

Testing an HTML Page on the Android Emulator Browser

HTMLonAndroidAlthough you can easily test your HTML page’s responsive design using Chrome’s Mobile Emulation feature, you can also do it, albeit the harder way, by loading the page on the Android emulator’s browser.

First you must run the Android Virtual Device (AVD) Manager to launch your Android emulator.  You don’t necessarily have to run the IDE that came with your Android emulator (e.g. Eclipse or Android Studio).  You can use the batch file android.bat which you can find under sdk/tools of your Android installation folder.  In the command prompt, just type in “android.bat avd”.

Once you have the AVD manager running, select the device you want to emulate.  But before starting the device, make sure you have specified a size for the SD card, as we will be using this to store the HTML page.  2GB should be OK.

Next, you need to copy the HTML page from the computer to the Android emulator’s SD card storage using the Android Debug Bridge program or adb.exe, which you can find under sdk/platform-tools.  Using a command prompt, run adb with the following options:

  • “adb devices” which will list the devices attached including the emulator ones.  To connect to the emulator you just started, you need to get the device number assigned to the emulator from the device list.  Or you can get the number from the emulator window bar.
  • “adb connect localhost:5554” which will connect you to the device emulator.   The number 5554 should be replaced with the device number for your emulator.
  • “adb push C:\YourFolder\YourHTMLPage.html sdcard/.”  which will copy your HTML page from your computer’s local folder to the Android emulator’s sdcard folder.  Note that the Android OS is based on Linux kernel which is why the destination path follows the Linux syntax.
  • “adb shell” which will bring you to the Android emulator file system.  You can go to the SD card folder to check if your HTML page was copied successfully by entering “cd sdcard” and then “ls –al”.  It’s exactly a Linux file system at your fingertip.  If you want to create a folder under the SD card folder you can use mkdir.  To get out of the shell, just type in exit.

You can also copy any accompanying CSS and JavaScript files for the HTML page you just copied.

Now you are ready to view the HTML page on the Android emulator browser.  On the emulator, open up the browser and type in the URL file:///sdcard/YourHTMLPage.html on the address window.

Note that by default, these mobile browsers will automatically shrink the page to fit the mobile device width.  The following meta tag should be used to override this and display the page at 100 percent.

<meta name="viewport" content="width=device-width,initial-scale=1.0"/>