Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Application Programming › Spot welding with C# (Extension methods)
New Posts  All Forums:Forum Nav:

Spot welding with C# (Extension methods)

post #1 of 5
Thread Starter 
After a few topics on the deep end of the magic that happens inside the computer, this time we will move up the ladder slightly to demonstrate a higher level concept that was introduced with Visual C# 3.0 and Visual Basic .NET 9: Extension methods. We will be focusing on how to use this concept in C# only.

What are extension methods?

Extension methods are a compiler-level "syntactic sugar" that basically allow you to spot weld additional methods onto classes that already exist, and make them appear (via compiler voodoo) as if they were defined in the class to start with. The important thing that I would like to reiterate is that extension methods are implemented at the compiler-level.

What is the point of an extension method?

This is a good question, because at first you might not really know what to use this language feature for. As said before, extension methods allow you to bolt on additional functionality to an existing class and make that functionality accessible in the exact same way as if it were defined in the class to start with. They are mainly used to simplify operations on an object and to permit code re-use. It is also handy when you want to bold on functionality to a class of which you do not control the source code (for example from a 3rd party assembly).

For example, lets take the String class in the .NET Framework (System.String). For the sake of the example, let say that my program converts lots of strings to upper case, and then writes them out to the console. Assuming extension methods did not exist, I could implement this two ways:

1. Call System.String.ToUpper() and Console.WriteLine() each time I need this operation.
2. Create a static helper class (for example StringHelpers) and define a static method method that does the same as (1). Call the static helper method each time I need this operation.

Of course, this section would hardly be complete without a code sample:

Implementation 1:
Code:
string example = "VB is better than Huddler";
Console.WriteLine( example.ToUpper() );

Of course, this implementation does not permit code re-use. What if we decided to convert the string to lowercase in a later revision of the program? We'd need to change many places in the program!

Implementation 2:
Code:
public static class StringHelpers
{
    public static void ConvertAndPrint( string input )
    {
        Console.WriteLine( input.ToUpper() );
    }
}

/* Usage */
string example = "VB is better than Huddler";
StringHelpers.ConvertAndPrint( example );

This implementation is better because it provides the ability to re-use code and makes it easier to change the behavior (only need to modify a single location). However, it is not quite as elegant as an extension method.

Implementing an extension method.

Interestingly enough, an extension method in C# is very similar to our static class + static method described in Implementation 2 above. In C#, an extension method must be a static method inside a static class, however for each method that is to be an extension method, the first parameter is decorated with the "this" modifier - this is the clue to the compiler that it is an extension method. Additionally, the first parameter MUST be the type/class that we want to extend. I'll demonstrate this below, and we will stick with our example from above:
Code:
 /* You can name the class anything, but I like to name it with the class I am extending and suffix it with "Extensions" */
public static class StringExtensions
{
    /* Note the "this" modifier before the first parameter */
    public static void ConvertAndPrint( this string input ) 
    {
        /* We should always check for null in an extension method */
        if ( string.IsNullOrEmpty( input ) )
        {
            return;
        }

        Console.WriteLine( input.ToUpper() );
    }
}

Now, here is the fun part where we get to use the magic of the compiler. We can call the extension method directly off our string instance variable, like this (continuing the example):
Code:
/* Usage */
string example = "VB is better than Huddler";
example.ConvertAndPrint();

The compiler automatically passes the instance to the extension method, so we call the method without any parameters - and it looks just like the ConvertAndPrint method was defined in the System.String class to begin with! Behind the scenes, though, the compiler generates code that does exactly the same as Implementation 2 above. You will notice this is the case if you use a program like Reflector to inspect the generated IL of both examples (advanced users).

I am getting a "Cannot resolve symbol XXX", where "XXX" is the name of my extension method. What is going on?

I did not use namespaces in my examples above, however if you defined your extension method static class inside a namespace and are trying to call it from a different namespace, you must import the namespace (in C# this is done via the using statement) from which the extension method static class is defined.

Other mistakes include not using a static class or method, or forgetting the "this" modifier on the first parameter of the extension method.

Happy welding!
Ol' Sandy
(28 items)
 
"Zeus"
(12 items)
 
Elite Preview
(6 items)
 
CPUMotherboardGraphicsRAM
Intel Xeon E3-1230v3 Gigabyte GA-Z97X-UD5H-BK MSI Gaming GTX 980 Kingston 32GB (4x8) 
Hard DriveHard DriveHard DriveHard Drive
Plextor PX-256M5S 256GB Samsung EVO 1TB Hitachi HDS721010CLA332 Hitachi HDS723020BLA642 
Hard DriveHard DriveHard DriveOptical Drive
Hitachi HDS723020BLA642 Hitachi HUA722010CLA330 WDC WD10EARS-00Z5B1 TSSTcorp CDDVDW SH-S223B 
CoolingCoolingOSMonitor
Phanteks PH-TC14PE with TY-140's Lamptron FCv5 (x2) Windows 8 Pro 64-bit Dell U2412M 
MonitorMonitorMonitorKeyboard
Dell U2412M Dell U2212HM Dell U2713HM Topre Realforce 87UB | Ducky DK9087 G2 Pro 
PowerCaseMouseMouse Pad
Corsair AX-750 Corsair Obsidian 650D Logitech G700 XTRAC Ripper XXL 
AudioAudioAudioAudio
Beyerdynamic DT-770 Pro 250ohm Schiit Bifrost DAC Schiit Asgard 2 HiVi Swan M50W 2.1 
CPUMotherboardRAMHard Drive
Intel Xeon E5-2620 Super Micro X9SRL-F-B 128GB 1333MHz LSI 9271-8i 
OSPowerCase
VMware ESXi 5.5 SeaSonic SS-400FL2 Fractal Define R3 
CPUMotherboardGraphicsRAM
Intel Core i5-3437U HP EliteBook Folio 9470m  Intel HD Graphics 4000  16GB DDR3 SDRAM 
Hard DriveOS
256GB SSD Windows 10 Insider Preview 
  hide details  
Reply
Ol' Sandy
(28 items)
 
"Zeus"
(12 items)
 
Elite Preview
(6 items)
 
CPUMotherboardGraphicsRAM
Intel Xeon E3-1230v3 Gigabyte GA-Z97X-UD5H-BK MSI Gaming GTX 980 Kingston 32GB (4x8) 
Hard DriveHard DriveHard DriveHard Drive
Plextor PX-256M5S 256GB Samsung EVO 1TB Hitachi HDS721010CLA332 Hitachi HDS723020BLA642 
Hard DriveHard DriveHard DriveOptical Drive
Hitachi HDS723020BLA642 Hitachi HUA722010CLA330 WDC WD10EARS-00Z5B1 TSSTcorp CDDVDW SH-S223B 
CoolingCoolingOSMonitor
Phanteks PH-TC14PE with TY-140's Lamptron FCv5 (x2) Windows 8 Pro 64-bit Dell U2412M 
MonitorMonitorMonitorKeyboard
Dell U2412M Dell U2212HM Dell U2713HM Topre Realforce 87UB | Ducky DK9087 G2 Pro 
PowerCaseMouseMouse Pad
Corsair AX-750 Corsair Obsidian 650D Logitech G700 XTRAC Ripper XXL 
AudioAudioAudioAudio
Beyerdynamic DT-770 Pro 250ohm Schiit Bifrost DAC Schiit Asgard 2 HiVi Swan M50W 2.1 
CPUMotherboardRAMHard Drive
Intel Xeon E5-2620 Super Micro X9SRL-F-B 128GB 1333MHz LSI 9271-8i 
OSPowerCase
VMware ESXi 5.5 SeaSonic SS-400FL2 Fractal Define R3 
CPUMotherboardGraphicsRAM
Intel Core i5-3437U HP EliteBook Folio 9470m  Intel HD Graphics 4000  16GB DDR3 SDRAM 
Hard DriveOS
256GB SSD Windows 10 Insider Preview 
  hide details  
Reply
post #2 of 5
Subbed, fun read thumb.gif
My Rig
(14 items)
 
Ex-wife's Rig
(15 items)
 
 
CPUMotherboardGraphicsRAM
Core i5 4460 AsRock H81M-DG4 Sapphire Rx470 Platinum KVR 1600 16Gb 
Hard DriveHard DriveCoolingOS
2x Seagate 3Tb Samsung 850 EVO 120 Scythe Ninja 3 Rev.B Windows 10 Pro 
MonitorKeyboardPowerCase
Fujitsu Siemens A17-2A Logitech K280e SuperFlower SF-550K12XP Thermaltake Versa H25 
MouseAudio
Logitech G402 Sony MDR XD150 
CPUMotherboardGraphicsRAM
Athlon 750K 4.0Ghz AsRock FM2A75 Pro4+ Sapphire R9 270X Dual-X Kingston 2x4Gb 1600 
Hard DriveHard DriveOptical DriveCooling
Samsung 850 EVO 120  Western Digital 320Gb LiteON DVD-RW CoolerMaster Hyper Z600 
OSMonitorKeyboardPower
Windows 7 Pro x64 Toshiba 32" FullHD TV Logitech FSP Hexa 550 
CaseMouse
DeLUX Logitech 
  hide details  
Reply
My Rig
(14 items)
 
Ex-wife's Rig
(15 items)
 
 
CPUMotherboardGraphicsRAM
Core i5 4460 AsRock H81M-DG4 Sapphire Rx470 Platinum KVR 1600 16Gb 
Hard DriveHard DriveCoolingOS
2x Seagate 3Tb Samsung 850 EVO 120 Scythe Ninja 3 Rev.B Windows 10 Pro 
MonitorKeyboardPowerCase
Fujitsu Siemens A17-2A Logitech K280e SuperFlower SF-550K12XP Thermaltake Versa H25 
MouseAudio
Logitech G402 Sony MDR XD150 
CPUMotherboardGraphicsRAM
Athlon 750K 4.0Ghz AsRock FM2A75 Pro4+ Sapphire R9 270X Dual-X Kingston 2x4Gb 1600 
Hard DriveHard DriveOptical DriveCooling
Samsung 850 EVO 120  Western Digital 320Gb LiteON DVD-RW CoolerMaster Hyper Z600 
OSMonitorKeyboardPower
Windows 7 Pro x64 Toshiba 32" FullHD TV Logitech FSP Hexa 550 
CaseMouse
DeLUX Logitech 
  hide details  
Reply
post #3 of 5
Thread Starter 
Quote:
Originally Posted by ronnin426850 View Post

Subbed, fun read thumb.gif

Thanks! biggrin.gif
Ol' Sandy
(28 items)
 
"Zeus"
(12 items)
 
Elite Preview
(6 items)
 
CPUMotherboardGraphicsRAM
Intel Xeon E3-1230v3 Gigabyte GA-Z97X-UD5H-BK MSI Gaming GTX 980 Kingston 32GB (4x8) 
Hard DriveHard DriveHard DriveHard Drive
Plextor PX-256M5S 256GB Samsung EVO 1TB Hitachi HDS721010CLA332 Hitachi HDS723020BLA642 
Hard DriveHard DriveHard DriveOptical Drive
Hitachi HDS723020BLA642 Hitachi HUA722010CLA330 WDC WD10EARS-00Z5B1 TSSTcorp CDDVDW SH-S223B 
CoolingCoolingOSMonitor
Phanteks PH-TC14PE with TY-140's Lamptron FCv5 (x2) Windows 8 Pro 64-bit Dell U2412M 
MonitorMonitorMonitorKeyboard
Dell U2412M Dell U2212HM Dell U2713HM Topre Realforce 87UB | Ducky DK9087 G2 Pro 
PowerCaseMouseMouse Pad
Corsair AX-750 Corsair Obsidian 650D Logitech G700 XTRAC Ripper XXL 
AudioAudioAudioAudio
Beyerdynamic DT-770 Pro 250ohm Schiit Bifrost DAC Schiit Asgard 2 HiVi Swan M50W 2.1 
CPUMotherboardRAMHard Drive
Intel Xeon E5-2620 Super Micro X9SRL-F-B 128GB 1333MHz LSI 9271-8i 
OSPowerCase
VMware ESXi 5.5 SeaSonic SS-400FL2 Fractal Define R3 
CPUMotherboardGraphicsRAM
Intel Core i5-3437U HP EliteBook Folio 9470m  Intel HD Graphics 4000  16GB DDR3 SDRAM 
Hard DriveOS
256GB SSD Windows 10 Insider Preview 
  hide details  
Reply
Ol' Sandy
(28 items)
 
"Zeus"
(12 items)
 
Elite Preview
(6 items)
 
CPUMotherboardGraphicsRAM
Intel Xeon E3-1230v3 Gigabyte GA-Z97X-UD5H-BK MSI Gaming GTX 980 Kingston 32GB (4x8) 
Hard DriveHard DriveHard DriveHard Drive
Plextor PX-256M5S 256GB Samsung EVO 1TB Hitachi HDS721010CLA332 Hitachi HDS723020BLA642 
Hard DriveHard DriveHard DriveOptical Drive
Hitachi HDS723020BLA642 Hitachi HUA722010CLA330 WDC WD10EARS-00Z5B1 TSSTcorp CDDVDW SH-S223B 
CoolingCoolingOSMonitor
Phanteks PH-TC14PE with TY-140's Lamptron FCv5 (x2) Windows 8 Pro 64-bit Dell U2412M 
MonitorMonitorMonitorKeyboard
Dell U2412M Dell U2212HM Dell U2713HM Topre Realforce 87UB | Ducky DK9087 G2 Pro 
PowerCaseMouseMouse Pad
Corsair AX-750 Corsair Obsidian 650D Logitech G700 XTRAC Ripper XXL 
AudioAudioAudioAudio
Beyerdynamic DT-770 Pro 250ohm Schiit Bifrost DAC Schiit Asgard 2 HiVi Swan M50W 2.1 
CPUMotherboardRAMHard Drive
Intel Xeon E5-2620 Super Micro X9SRL-F-B 128GB 1333MHz LSI 9271-8i 
OSPowerCase
VMware ESXi 5.5 SeaSonic SS-400FL2 Fractal Define R3 
CPUMotherboardGraphicsRAM
Intel Core i5-3437U HP EliteBook Folio 9470m  Intel HD Graphics 4000  16GB DDR3 SDRAM 
Hard DriveOS
256GB SSD Windows 10 Insider Preview 
  hide details  
Reply
post #4 of 5
Interesting
    
CPUMotherboardGraphicsGraphics
Intel Core i7 860 Asus P7P55D-E Pro MSI GTX560 Ti TwinFrozr II MSI GTX560 Ti TwinFrozr II 
RAMHard DriveHard DriveHard Drive
Corsair 8GB DDR3 OCZ Vertex 3 Western Digital Caviar Black Western Digital Caviar Green 
Hard DriveOptical DriveCoolingOS
Samsung 840 Pro Lite-On 24x DVD-RW CoolerMaster V8 Windows 8.1 Professional 
OSMonitorMonitorMonitor
Debian 7.1 Samsung S22B350H Samsung S22B350H Samsung S22B350H 
KeyboardPowerCaseMouse
Ducky Shine II Corsair HX850 CoolerMaster Storm Enforcer Logitech M500 
Mouse PadAudio
Razer Goliathus Microsoft LifeChat LX 3000 
  hide details  
Reply
    
CPUMotherboardGraphicsGraphics
Intel Core i7 860 Asus P7P55D-E Pro MSI GTX560 Ti TwinFrozr II MSI GTX560 Ti TwinFrozr II 
RAMHard DriveHard DriveHard Drive
Corsair 8GB DDR3 OCZ Vertex 3 Western Digital Caviar Black Western Digital Caviar Green 
Hard DriveOptical DriveCoolingOS
Samsung 840 Pro Lite-On 24x DVD-RW CoolerMaster V8 Windows 8.1 Professional 
OSMonitorMonitorMonitor
Debian 7.1 Samsung S22B350H Samsung S22B350H Samsung S22B350H 
KeyboardPowerCaseMouse
Ducky Shine II Corsair HX850 CoolerMaster Storm Enforcer Logitech M500 
Mouse PadAudio
Razer Goliathus Microsoft LifeChat LX 3000 
  hide details  
Reply
post #5 of 5
WARNING!!!!

Do NOT misuse the mechanic as the default way to add all kinds of stuff to existing "core" classes, those that make up the basic building blocks of your application, like string, int, long, and DateTime classes.

Next thing you'll know you end up with hundreds of methods on your String class that are useful but not quite because they're too specific to sit at that common level.

Pick the right class to extend. What you have to think about is "How useful is the extention from the perspective of using that class. Will I use it often and in what kinds of different scenarios?" If you can't really come up with ideas, your function may be too specific to be added as an extention method.

When you write stuff for re-use, always question its "usability scope". Try to eliminate parameters specific to a certain thing you're trying to implement etc. Books can be written about this =)
The Box
(15 items)
 
  
CPUMotherboardGraphicsRAM
i7 5960X (4.444GHz/4.242GHz) ASUS Rampage 5 Extreme MSI Gaming GTX 970 4GB (2 way SLI) 16GB G.Skill Ripjaws 4 (3232MHz, 15-15-17-38-1T) 
Hard DriveHard DriveOSMonitor
ICH: 2x160GB-R0 EX4650: 4x1.5TB-R5 Windows 7 Ultimate IIyama XB2776QS 1440p 
KeyboardPowerCaseMouse
Logitech G510s SilverStone Strider 850W Mountain Mods U2-UFO Logitech G502 
Audio
Onboard Realtek HD 
  hide details  
Reply
The Box
(15 items)
 
  
CPUMotherboardGraphicsRAM
i7 5960X (4.444GHz/4.242GHz) ASUS Rampage 5 Extreme MSI Gaming GTX 970 4GB (2 way SLI) 16GB G.Skill Ripjaws 4 (3232MHz, 15-15-17-38-1T) 
Hard DriveHard DriveOSMonitor
ICH: 2x160GB-R0 EX4650: 4x1.5TB-R5 Windows 7 Ultimate IIyama XB2776QS 1440p 
KeyboardPowerCaseMouse
Logitech G510s SilverStone Strider 850W Mountain Mods U2-UFO Logitech G502 
Audio
Onboard Realtek HD 
  hide details  
Reply
New Posts  All Forums:Forum Nav:
  Return Home
  Back to Forum: Application Programming
Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Application Programming › Spot welding with C# (Extension methods)