February 2004 - Posts
Streams are interesting (and very useful) entities. We can define them as an abstraction of a series of bytes of data in some store which we can read or write to. Stream is really powerful concept as it provides a unified way of accessing data present in various sources like a file, a network source or some memory location. We weren't really exposed to the concept of streams in VB6, except for some sporadic usage of the ADO Stream object.
.NET has extensive support for Streams, System.IO.Stream being the base class for all streams. Depending on the underlying backing store, you have specific stream classes like FileStream, CryptoStream, NetworkStream and MemoryStream etc. Here, I am particularly interested in MemoryStream which has memory as the backing store. I can think of two situations where MemoryStream can be really useful:
1. For Cloning objects:
MemoryStream provides an elegant way of cloning objects wherein, you can serialize an object to a memory stream and then deserialize that back into a new object
For more info on cloning objects, refer to http://www.codeproject.com/dotnet/Clone.asp
2. Using memory stream as a temporary buffer:
It is pretty customary to open up a FileStream object (like a log file) early in the application, write to it at regular intervals, and then close it before terminating the application. Taking a write lock on the file for a large amount of time can be unacceptable, especially if you have other applications or threads waiting to write to the same file. So, as a remedy, you can write the entries to a memorystream and a some logical point of time, just copy the contents to the FileStream by using the WriteTo method. I suppose, this is analogous to the “acquire late, release early” semantics of transaction related locks.
Refer to this article for more insight into streams: http://archive.devx.com/dotnet/articles/ep070202/ep070202-1.asp. What you have seen is just the tip of the iceberg!
Most of us probably wouldn't know this. The .NET SDK Installation (Of course VS.NET too) silently hides pots of gold on your machine. Unearth them now from here:
<Your SDK Install Folder>\SDK\v1.1\Tool Developers Guide\docs
If you don’t find it , you can get them from here: http://msdn.microsoft.com/net/ecma/
If you are a religious VB.NET developer, you have to mark this as your favorite. Panopticon Central is Paul Vick's blog. Fantastic stuff about VB.NET, code optimization, performance etc. If you are wondering who Paul Vick is, he is the person who has authored the VB.NET language specification and is certainly one of the best authority on the VB.NET language. (I had blogged about this a couple of days back)
Also make sure you bookmark your favorite blogs here: http://blogs.gotdotnet.com/ and http://blogs.msdn.com/
Many a time, you will bump into requirements like these:
1. How do I find the current .NET runtime version ?
2. How do I find the install directory of .NET framework?
There are many ways to get this information:
You can use System.Environment.Version.ToString() to get the current .NET runtime version or get the value in this Registry key to get the install folder: HKLM\Microsoft\.NetFramework\InstallRoot
The other option gives you the answer for both the questions. That is
System.Runtime.InteropServices.RuntimeEnvironment class. This provides you very useful static (shared) methods, foremost among them are GetSystemVersion (for Q1) and GetRuntimeDirectory (for Q2)
There are a lot of interesting things to note here:
1) Firstly, RuntimeEnvironment class in the InteropServices namespace. InteropServices is a namespace typically used for COM Interop and P/Invoke services. Perhaps, this will be useful in cases of custom runtime hosting or related stuff.
2) Closely check out the Enviromment class mentioned above. This is one hell of a useful class giving a wealth of information like access to system environment variables (like PATH, Windir etc), OSVersion etc. and also gives other potentially platform neutral stuff like NewLine. So, technically, it is better to use Environment.NewLine instead of VbCrLf
3) Finally, the point to ponder about is - when is it that I need to know the runtime directory? I would say - cases when I need to run utilities like installutil, regasm, regsvs from my application etc (A batch compile action, installer or something like that). Note that this is the directory where you find all the .NET compilers and tools.
In my opinion, the language specification is what really answers all the "Why" questions of a language. The books you buy probably answer only the "What"s of a language.You can download the VB.NET Language specification here (202 pages). A must read for VB.NET devs again.
http://www.microsoft.com/downloads/details.aspx?familyid=bf32527d-187c-49fa-8c67-9e9105535550&displaylang=en
BTW, you can get the C# specification at
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf
You might see the difference in the URLs where these are available. C#, as you know, is now an ECMA standard language you can think of VC# as Microsoft's implementation of this standard, just like .NET Framework, .NET Compact Framework and SSCLI are implementations of CLI. VB.NET is ofcource, proprietary.
Enums are useful for listing options that are generally mutually exclusive. For instance:
Enum DataProviders
SQLCLient
OLEDB
ODBC
ODP
End Enum
In not so rare situations, you would require an enumeration which can give options that can be a combination of values (some wonks call this a Bitwise Or). Something like:
Public Enum FileAccess
Read
Write
ReadWrite
End Enum
Here, ReadWrite option means Read Or (bitwise) Write option. Is it possible to do this in VB.NET enums? If possible, how would this be useful?
Well, there is a custom attribute called FlagsAttribute which does the trick for us. This is how:
<Flags()>_
Public Enum FileAccess
Read = 1
Write = 2
ReadWrite = 3 ' Read Or Write
End Enum
Note that I have explicitly provided values for Read and Write, which notably are powers of two, and ReadWrite is Read Or Write (1 Or 2 = 3) . FlagsAttribute is used in tons of places across the FCL and are pretty useful to aggregate values which represent bit flags. They are a better alternative to using separate constants for flags. Have a look at FileAttributes enum, which is another good example. To that end try this:
Console.WriteLine(CType(2082, FileAttributes).ToString)
"Hidden, Archive, Compressed" is what you will see. Cool isn't it.