Explicit Interface Implementation
In C#, you can explicitly implement interface members in your class or struct. C# language specification explains it better than I can:
For purposes of implementing interfaces, a class or struct may declare explicit interface member implementations. An explicit interface member implementation is a method, property, event, or indexer declaration that references a fully qualified interface member name.
Here’s a small example:
public interface IMyInterface { String SayHello(); } class MyClass : IMyInterface { string IMyInterface.SayHello() { return "Hello from IMyInterface!"; } }
The MyClass explicitly implement the SayHello method from IMyInterface. The interesting thing about explicitly implemented member is that they’re only accessible when accessed trough the interface. From C# language specification again:
It is not possible to access an explicit interface member implementation through its fully qualified name in a method invocation, property access, or indexer access. An explicit interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name.
The below code won’t compile, as the SayHello method is only visible trough the interface:
var o = new MyClass(); Console.WriteLine("MyClass: {0}", o.SayHello());
‘MyClass’ does not contain a definition for ‘SayHello’ and no extension method ‘SayHello’ accepting a first argument of type ‘MyClass’ could be found (are you missing a using directive or an assembly reference?)
Now, let’s add a second method called SayHello with the exact same signature to the class, defined as such:
public string SayHello() { return "Hello from MyClass"; }
This time, the previous code will compile, and will print “Hello from MyClass” in the console.
To access the explicitly implemented method, we have to go trough the interface, calling it as such:
var p = (IMyInterface)o; Console.WriteLine("IMyInterface: {0}", p.SayHello());
This will print “Hello from IMyInterface” in the console, as expected.
The two primary purpose of explicit interface implementation, as described in the C# language specification, are twofold:
- Because explicit interface member implementations are not accessible through class or struct instances, they allow interface implementations to be excluded from the public interface of a class or struct. This is particularly useful when a class or struct implements an internal interface that is of no interest to a consumer of that class or struct.
- Explicit interface member implementations allow disambiguation of interface members with the same signature. Without explicit interface member implementations it would be impossible for a class or struct to have different implementations of interface members with the same signature and return type, as would it be impossible for a class or struct to have any implementation at all of interface members with the same signature but with different return types.
On top of this, a common usage, as described in C# in Depth (2.2.2, page 46), is to palliate the lack of covariant return types (the example is on IClonable interface, see this topic on Stack Overflow).
C# 4.0 and dynamic keyword
With the new dynamic keyword in C# 4.0, a method call on a dynamic object is resolved at runtime. Is is therefore impossible to access the explicitly implemented member on a dynamic object.
dynamic q = new MyClass(); dynamic r = (IMyInterface)q; Console.WriteLine("MyClass: {0}", q.SayHello()); Console.WriteLine("IMyInterface: {0}", r.SayHello());
The above code will print “Hello from MyClass” twice, as SayHello is called on a object who’s runtime type is MyClass. The only way to access IMyIntergace’s SayHello implementation is to cast q or r to IMyInterface before the call:
Console.WriteLine("IMyInterface: {0}", ((IMyInterface) q).SayHello());
Restoring Files From a Complete PC Backup
Today, I was searching for some files that I used to have on my PC, two installs ago (I’m running Window 7 RC now, before that I was running Windows 7 Beta and before that Windows Vista SP1).
However, I apparently missed something when migrating, as I could not find the files. Hopefully, I could find these on the few backups I made before installing the RC. I made backups using Complete PC Backup feature of Windows 7/Vista.
I wondered how to restore only files from an image that was not from this installation. Restore center does not find other installs backup, hence you cannot use it to restore files from another install’s backup files. As I browsed in the backup folder (that is named WindowsImageBackup), I realized that the files stored in there are some .vhd and a bunch of xml files.
I remembered that one of Windows 7 new feature is that you can mount an .vhd file in the disk manager. I never did this before, and it turned out to be piece of cake. Just read here.
Once this was done, I could access all the content of the backed up drives, and restore what I needed.
Sadly, the files were not there, they were on an install I apparently got rid of, so they are lost forever… Now that I have a Windows Home Server at home, I won’t happen again!
AHCI and Windows 7
I only discovered lately that my SATA drives were configured as IDE on my mother board’s BIOS. However, simply selecting AHCI instead of IDE in the BIOS makes it impossible to boot Windows 7 that will bluescreen.
Windows 7 supports AHCI natively, but the drivers a disabled if the drives are configured as IDE when you install. In order to make it work, you have to enable Windows 7’s AHCI drivers first, then configure the drives in the BIOS.
You can see if AHCI driver is enabled by looking in the Device Manager:
To enable Windows’ drivers, you have to change a specific key in the registry. The steps are described on Microsoft’s support website.
Once it is done, reboot, go in the BIOS and configure the SATA drives as AHCI and let Windows boot. Once you are logged in, Windows will tell you that new hardware is being installed, and once it is done, it will ask for reboot. Reboot once more, and you’re done!
You can go back to the Device Manager to witness that the driver is now enabled:
Building Paths in C# and Java
When it comes to build full path files strings in C# or Java, I very often see methods being reinvented again and again.
However, both framework offer utility classes to do just that for you. An it has been developed by some of the most skilled developers on the planet. How can you beat that? So stop rolling out your own path building functions!
.NET Version (in C#)
I’m always astonished that so many developers don’t know the System.IO.Path utility static class of the .NET Framework.
As an example, see this code:
String file1 = Path.Combine(@"C:\tmp\test\", "test.txt"); String file2 = Path.Combine(@"C:\tmp\test", "test.txt"); //file1 == file2 //"C:\tmp\test\test.txt" Console.WriteLine("File: {0}", file1);
Doesn’t matter if you forgot the “\” at the end of the directory string, it will be added. If it’s already there, it’s also fine! If you don’t know that stuff yet, have a look at the others methods available.
Now, onto Java.
Java Version
Java has the File class to do that. It’s very easy to use, but it doesn’t work the same way. You have to instantiate a new File object every time, instead of calling a static method like in .NET.
File file1 = new File("C:\\tmp\\test", "test.txt"); File file2 = new File("C:\\tmp\\test\\", "test.txt");
Now, this object is an abstract representation of the “C:\tmp\test\test.txt” file, so if you call toString() on it, you get that path as a string.
Side Notes
Two interesting things I noticed while writing this.
First, a difference between .NET and Java path creators. The .NET Path.Combine will return only the second string if it starts with the “\” character, while the Java File class will ignore it. the .NET class probably assumes that it’s a relative path, while the Java class ignores it.
Second, if you try to create an instance of the .NET Path class, Visual Studio will give you the following error message: “Cannot create an instance of the abstract class or interface ‘System.IO.Path’”. Once you tried to build, if fails and the error message changes to “Cannot create an instance of the static class ‘System.IO.Path’”. It’s clearly related to Visual Studio, but it’s the first time I notice that behavior (the first error message was quite suspicious with the “abstract class or interface” thingy). Anyway, Visual Studio warns you that it cannot be done, which is the important thing, then it refines it’s error message based on the output of the compiler.
Boxing and Unboxing in .NET
I realized that the way boxing and unboxing works in .NET was not something I knew well, so I decided to write some small recap along with code to test boxing/unboxing behaviors.
Some Theory
In .NET, even if value types derive from the uber root object System.Object, they need the special boxing operation to be treaded as object.
A good explanation is given in the C# Language Specification:
A value of a class type can be converted to type
objector to an interface type that is implemented by the class simply by treating the reference as another type at compile-time. Likewise, a value of typeobjector a value of an interface type can be converted back to a class type without changing the reference (but of course a run-time type check is required in this case).Since structs are not reference types, these operations are implemented differently for struct types. When a value of a struct type is converted to type
objector to an interface type that is implemented by the struct, a boxing operation takes place. Likewise, when a value of typeobjector a value of an interface type is converted back to a struct type, an unboxing operation takes place.
So, when a value type needs to be converted to an object, it is boxed in a reference type. As stated, boxing means that the value type gets copied in the wrapping reference type.
A boxing conversion implies making a copy of the value being boxed. This is different from a conversion of a reference-type to type
object, in which the value continues to reference the same instance and simply is regarded as the less derived typeobject.
The important thing to bear in mind is that boxing and unboxing happens automatically. Everywhere an reference type is expected but a value type is used instead, the value type is automatically boxed.
Another important point is that if the value type has overrides some of the virtual methods inherited from object, invocation of these methods on the value type does not require boxing.
Some Examples
Now, let’s see how it works, and what are the caveats.
A first interesting case is directly taken from Bill Wagner’s “Effective C#”. Consider this code:
Console.WriteLine("A few numbers:{0}, {1}, {2}", 25, 32, 50);
WriteLine takes an array of object references as parameters. This means that the three value types will be boxed before calling the ToString() method on them. To avoid this, ToString() method should explicitely be called on each of these int in order to provide WriteLine with string which are reference types, so there is no boxing.
Console.WriteLine("A few numbers:{0}, {1}, {2}", 25.ToString(), 32.ToString(), 50.ToString());
So, that’s one thing to keep in mind. It’s good for performances reasons, but it doesn’t introduce any bug.
The next step is the copy of the value type in the box itself, meaning that any change to the copied value type in the box will not be reflected in the original copy. Also, when unboxing, the value from the box is copied again.
int i = 5; var j = (object)i; i++; Console.WriteLine("i: {0}", i); //Prints 6 Console.WriteLine("j: {0}", j); //Prints 5 j = (object)i; var k = (int)j; k++; Console.WriteLine("j: {0}", j); //Prints 6 Console.WriteLine("k: {0}", k); //Prints 7
When you think about it, is quite easy and it makes a lot of sense, as in C#, things are copied by value (meaning that when you copy a reference type, you copy the value of the reference, which is what the variable stores).
Last funny thing:
Object.ReferenceEquals(5, 5); //Returns false
It’s easy to understand. The two value types (5 and 5) are each boxed in a separate reference type, which don’t have the same reference.
A small warning tough, everything I write here is from quite trusted sources, but it may happen that I misunderstood something, so ask a real expert if you want to be sure…
