Is 'using' a C# keyword?
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.
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.
According to Microsoft it's a keyword.
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.
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
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().
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).
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/
精彩评论