views:

276

answers:

7

If an object realizes IDisposable in C# one can write

using(DisposableFoo foo = new DisposableFoo())

I've always wondered why the using looks like a C# keyword, but requires an interface defined in the .Net framework. Is using a keyword (in this context, obviously it is for defining your library imports), or has Microsoft overloaded it's use in Visual Studio/.Net framework? I wouldn't have expected a C# keyword to depend on a library.

+7  A: 

According to Microsoft it's a keyword.

Brian Agnew
+1  A: 

I think using is a keyword that essentially make your code

B b=new B();//can get resource outside using statement but will dispose inside of it
using(A a=new A(),b,C c=new C() //A,B,C are variable of types that implement IDisposable){
SomeCode//Some code to execute
}

into

B b= new B();
try{ 
A a= new A();
C c= new C();//B isn't here since

SomeCode//execute the code

}finallly{
a.Dispose();//The reason A,B,C need to implement IDisposable
b.Dispose();//is so the compiler can make sure that they can call Dispose()
c.Dispose();
}

The important bit with why IDisposable is used is because c# is strongly typed, behind the scenes its calling Dispose(), and implementing IDisposable tells the compiler it can.

Similar to how foreach is with IEnumerable and the IEnumerator (calling GetEnumerator(),Current(),MoveNext() although I think it doesn't do this with arrays only collection classes).

Roman A. Taycher
I think the using(A = a new A(), C c = new C()) won't work. Compiler returns this message: "Cannot use more than one type in a for, using, or declaration statement." I know it's just a detail of what you were explaining, but no one mentioned it and that's what I was looking for.
Alpha
+7  A: 

it's a keyword construct that requires a IDisposable, because it acts on the object's Dispose method. It's not too far fetched to have a keyword use a type. If is a keyword and it requires a condition (IE: Boolean) type.

Tony Abrams
+5  A: 

Yes, it is a keyword. The C# language relies on the framework for implementing many keywords.

Other keywords that rely on the framework is for exmaple foreach (uses IEnumerable) and the LINQ syntax (when used with LINQ to Objects requires the System.Linq library).

Even keywords like int and string rely on the types System.Int32 and System.String in the framework.

Guffa
Actually using is uncommon *because* it demands an interface. You can use foreach without IEnumerable, and LINQ without any special libraries (it doesn't even need extension methods, really)
Marc Gravell
@Mark Gravell: I think that it's actually foreach that is uncommon as it uses a duck typing that is uncharacteristic for C#, that requires the implementation of IEnumerable, but not the actual interface. I will clarify that it's LINQ to Objects that require the System.Linq library.
Guffa
@guffa LINQ meaning the language query syntax doesn't require any specific library. I could write a c# 3 / .net 2.0 console app that uses LINQ query syntax.
Marc Gravell
(without any dlls except mscorlib and System)
Marc Gravell
@Mark gravell: LINQ to What? What would you use for the compiler to implement the query?
Guffa
@Guffa all the compiler needs is the method patterns. for example a public instance Where method taking Converter<SomeType,bool>. it does not have to be Enumerable.Where, be an extension method, operate on IEnumerable or take Func<*>.
Marc Gravell
@Guffa in other words you could argue that the whole of LINQ is duck-typed (and a small thing; I won't get notified of @Mark replies-only @Marc; I only mention it to avoid my missing an interesting conversation)
Marc Gravell
@Marc Gravell: Yes, you don't need the framework library if you make your own replacement library...
Guffa
@Guffa no more a trick than foreach. Simply knowing the rules the compiler follows...
Marc Gravell
This answer has clearly provoked the most discussion and I've learnt the most from it - so I'm accepting this one.
RichK
+3  A: 

C# is tied fairy closely to the CLI, and the language spec uses a minimal number of runtime features. IDisposable for "using" is actually unusually rigid, as in most cases (for example "foreach", LINQ, etc) there is support both with and without the specific runtime implementation.

However, since the IDisposable /using construct is key to .NET I doubt you could make even a minimal (but legal) CLI without it, so it isn't really a problem to mention it in the language spec.

Other things that tie to specific types:

  • string concatenation (+ vs string.Concat)
  • extension methods
  • generic new()
  • [Serializable] (maps to an IL flag, not an attribute)
  • foreach (but can be used without any of the interfaces)
  • core base types (Enum Array Object ValueType Delegate)
  • expression-tree compiler (but nor described in the spec)

Etc

Marc Gravell
+2  A: 

Yes, there is a definitely coupling between the language and the support assemblies in the .NET framework. By far the most important one is mscorlib.dll, the home for the System.IDisposable interface declaration. It is so important that it isn't even listed in your C# project's References node. The C# compiler assumes it is always needed and will find it by itself, unless you use the special /nostdlib compile option.

Other examples of syntactic elements that require it:

  • array[], requires System.Array
  • [attributes], requires System.Attribute
  • catch, requires System.Exception
  • delegate, requires System.MulticastDelegate
  • type?, requires System.Nullable<>
  • params, requires System.ParamArrayAttribute
  • typeof, requires System.Type

There's coupling between all the basic types and their corresponding declaration in mscorlib (like Int32, String, Object, ValueType etc).

Later examples are the Linq query comprehension syntax, requiring System.Core.dll, and the dynamic keyword, requiring Microsoft.CSharp.dll. These examples are by no means exhaustive.

This is otherwise quite normal, even C compilers assume that a runtime library is available with primitives like memset() and ldiv().

Hans Passant
+1  A: 

using is a C# keyword that acts as a syntactic-sugar for dealing with IDisposible objects. As per MSDN

using block Defines a scope, outside of which an object or objects will be disposed.

The using statement allows the programmer to specify when objects that use resources should release them. The object provided to the using statement must implement the IDisposable interface. This interface provides the Dispose method, which should release the object’s resources.

Surprisingly even MSDN does not clarify how does this happen under the hood. It only says the object has to implement IDisposable interface that provides Dispose method on the object implementing the interface. So to dispose the object it will need to call the Dispose method on the object which will cleanup and release the resources used by the object.

Take a look at this example..

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BlogSamples
{
    class Program
    {
        static void Main(string[] args)
        {
            //Assume that Car is IDisposible.
            using (Car myCar = new Car(1))
            {
                myCar.Run();
            }
        }
    }
}

Compiler converts to code to look like this..

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BlogSamples
{
    class Program
    {
        static void Main(string[] args)
        {
            //Declare myCar object with FullName of the type as seen in IL.
            BlogSamples.Car myCar;

            //Instantiate the object by calling the constructor, matching the flow of IL.
            myCar = new Car(1);

            try
            {
                myCar.Run();
            }
            finally
            {
                if(myCar != null)
                    myCar.Dispose();
            }
        }
    }
}

To understand how exactly the using block works under the hood, I recommend you read this blog-post.

http://www.ruchitsurati.net/index.php/2010/07/28/understanding-%E2%80%98using%E2%80%99-block-in-c/

this. __curious_geek
Actually, I'd say it's a good thing that MSDN doesn't say what happens under the hood. Quite a few things MSDN details gives implementation details without much in the way of explanation as to what is an implementation detail, and what is required (stack vs heap when it comes to value and reference types would is a classic example). It would be nicer in a few ways if the separated these better. If it **also** detailed implementation that'd be nice, but I prefer to have normative text detail normative information.
Jon Hanna