Ben Biddington

Whatever it is, it's not about "coding"

Posts Tagged ‘.net

Why can’t I hang an extension method on a type?

leave a comment »

My brother asked me this. And while I don’t know, I did discover some interesting things along the way.

An extension method is nothing more than a compiler trick. It is simply a static method that takes an instance of the type being extended as an argument. That’s it.

The sugar part is that to you as a programmer, it appears to read more naturally in some cases.

They do not have any special privileges on private or protected members and they are not analagous to ruby module mixins (because the extended class cannot invoked extension methods).

[TBD: It is interesting that instance methods are supplied "this" as their first argument, see CIL]

[TBD: It is interesting that the compiler emits a callvirt instruction even in cases where call seems more appropriate just because callvirt has a null reference check. See: Why does C# always use callvirt?]

[TBD: Extensions are really a higher level abstraction because they operate only against public interface. An extension method is a client of the object it "extends"]

Example

namespace Examples {
    public class ExampleClass { }

    public static class Extensions {
        public static void ExtensionMethod(this ExampleClass instance) {
            instance.ToString();
        }
    }

    public class ThatUsesExampleClass {
        public void RunExample() {
            new ExampleClass().ExtensionMethod();
        }
    }
}

The interesting part is RunExample (because it invokes the extension method):

public void RunExample() {
    new ExampleClass().ExtensionMethod();
}

which compiles to:

.method public hidebysig instance void
RunExample() cil managed
{
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  newobj     instance void Examples.ExampleClass::.ctor()
    IL_0006:  call       void Examples.Extensions::ExtensionMethod(class Examples.ExampleClass)
    IL_000b:  nop
    IL_000c:  ret
} // end of method ThatUsesExampleClass::RunExample

It is clear that the compiler has done nothing more than redirect to a static method on a static class:

IL_0006:  call       void Examples.Extensions::ExtensionMethod(class Examples.ExampleClass)

Usage

The usual static method usage rules apply:

[Clean code chapter 6]
Procedural code (code using data structures) makes it easy to add new functions withoutchanging the existing data structures. OO code, on the other hand, makes it easy to add new classes without changing existing functions.

The complement is also true:
Procedural code makes it hard to add new data structures because all the functions must
change. OO code makes it hard to add new functions because all the classes must change.
So, the things that are hard for OO are easy for procedures, and the things that are
hard for procedures are easy for OO!

In any complex system there are going to be times when we want to add new data
types rather than new functions. For these cases objects and OO are most appropriate. On
the other hand, there will also be times when we’ll want to add new functions as opposed
to data types. In that case procedural code and data structures will be more appropriate.

Mature programmers know that the idea that everything is an object is a myth. Sometimes
you really do want simple data structures with procedures operating on them.

[TBD: Usage -- how does it fit with OO design?]

Back to the question

Still no answer.

But I can’t see any reason why the C# compiler couldn’t do the same for static constructs, but I wonder how you would express that on the extension method itself.  Perhaps that’s where the ExtensionAttribute comes in. Note: It currently is illegal to use the ExtensionAttribute directly.

But if you examine the IL for an extension method itself, you’ll see it has been applied:

.custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() =
    ( 01 00 00 00 )
.method public hidebysig static void
    ExtensionMethod(class Examples.ExampleClass 'instance') cil managed {

    .custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() =
        ( 01 00 00 00 ) 

    // Code size       9 (0x9)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldarg.0
    IL_0002:  callvirt   instance string [mscorlib]System.Object::ToString()
    IL_0007:  pop
    IL_0008:  ret
} // end of method Extensions::ExtensionMethod

Written by benbiddington

4 August, 2010 at 09:15

Posted in development

Tagged with , , , , ,

Windows services and net use

leave a comment »

We have some Windows services that need to access network shares, and even though we have net used, those resources are still unavailable. It appears this is because our services are running as LocalSystem.

How to check the connections available to LocalSystem

1. Open command prompt as LocalSystem

Follow these instructions to get a LocalSystem cmd prompt using at.exe.

Note: You can use at.exe only when the Schedule service is running, to find out:

sc query schedule

2. List connections

net use

You will see the set of connections available.

Note this set is different to the list generated by ordinary command prompt (your account).

How to add connection for LocalSystem

Don’t know, that method is not very automatable.

References

Written by benbiddington

27 April, 2010 at 13:37

Posted in development

Tagged with , , , , ,

Async operations and exceptions

leave a comment »

We have had the case where we’re creating a class that allows clients to block while internally it reads an entire stream asynchronously. This class encapsulates the state required to perform such a task.

While attempting to write unit tests for exceptions, we found that an exception thrown during the asynchronous operation would not be thrown to client. Debugging showed that the exception was being thrown, but no notification was being sent to the parent thread.

No such thing as unhandled exceptions on managed threads

[MSDN] [since .NET Framework v2.0] There is no such thing as an unhandled exception on a thread pool [or finalizer] thread. When a task throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then returns the thread to the thread pool.

Errors raised on a child thread are essentially lost when the thread exits. This means there is some work required to propagate these exceptions.

This requires a blocking wait on the part of the client, and a mechanism for storing the exception so the parent thread can read it.

As an example, we have implemented an AsyncStreamReader which contains a blocking ReadAll method. If an asynchronous read fails with an exception, that exception is exposed internally as a field, and the waiting thread is then signalled. Once the waiting thread wakes up it checks the exception field and throws it if required.

We have blocking Read operation that waits for an async read to complete. The notification mechanism is a ManualResetEvent (WaitHandle).

  1. T1: Invoke ReadAll.
  2. T1: Start async operation (spawns T2).
  3. T1: Wait.
    1. T2: Async operation encounters exception.
    2. T2: Store exception in _error field.
    3. T2: Signals T1.
    4. T2: Returns without triggering any subsequent reads.
    5. T2: Thread exits
  4. T1: Parent thread resumes (still inside ReadAll).
  5. T1: Checks _error field. If it is not null, throw it, otherwise return.
  6. T1: Exception is now propagated

References

Written by benbiddington

27 April, 2010 at 13:37

Follow

Get every new post delivered to your Inbox.