This page contains posting guidelines and answers to frequently asked questions (FAQs) on the microsoft.public.dotnet.languages.csharp newsgroup.
If you haven't posted on the C# newsgroup before, please read the posting guidelines and suggestions first - they should help you to get an answer quickly and without irritating anyone.
If you have seen a question come up frequently on the newsgroup and believe it should be part of the FAQ, please post it on the newsgroup with a subject line beginning with "FAQ Suggestion", including in the post both the question and a suggested answer. The answer can then be honed and discussed within the newsgroup before being added to the FAQ.
If you spot a mistake in the FAQ, please mail the FAQ maintainer. Please get the most up-to-date version of this FAQ before mailing, in case the maintainer changes. The most up-to-date version of the FAQ is currently available from http://www.yoda.arachsys.com/csharp/faq/ (also known as http://www.pobox.com/~skeet/csharp/faq/). If this changes, the version at the old "up-to-date" site will be changed to point to the new site, and so on - if the page you're looking at came from the site just mentioned, and you've just refreshed it or cleared your browser cache, you're looking at the latest version.
Many of the answers here are now also available on the C# Product Team's FAQ. When I get the chance, I'll link each answer to duplicated questions from here to there, as there are often lively discussions about the questions and answers.
The FAQs have been split into a few broad categories. In many senses, a lot of the FAQs aren't really appropriate for the C# newsgroup in the first place, but that's true of a lot of the posts in the group anyway, and I'd rather people were able to find the answer here than ask a possibly inappropriate question in the group. Where "my" and "I" are used, this tends to indicate Jon Skeet as the initial author of the FAQ. If many extra questions and answers are added which use the first person, I'll convert everything to the third person, but for now I think it'll suffice.
static and const together?string and System.String?override and new?as operator?Equals and when should I use ==?Nothing?addressof?MyClass?Me and MyBase?Initialize() on a reference-type array
fill the array with objects?
string to an int etc?Convert.ToInt32(string) and Int32.Parse(string)?(No questions yet.)
Dispose or Close?C# is a language created by Microsoft specifically for the .NET framework. It has been standardised by ECMA for version 1, and version 2 will no doubt go through ECMA when it's been fully released by Microsoft. It is similar in syntax to the C language of families, and also appears to borrow from Java and Delphi. (This is in no way a criticism of it - it's always good to learn from the mistakes and positive aspects of other things.)
.NET is a platform created by Microsoft. It consists of a virtual execution environment (including garbage collection, JITting, strong versioning, type and memory safety etc) and a large runtime library. It is at the heart of Microsoft's future strategy for the Windows platform, and will be a central part of the next release of Windows (Longhorn).
The .NET framework itself runs on all versions of Windows from Windows 98/NT4 upwards. It does not run on Windows 95 or NT3.5. For NT4, it requires service pack 6a.
There are various (mostly open source) projects to write a CLR (Common Language Runtime) on other operating systems such as Linux and BSD. The two best known are:
Strictly speaking, these are not actually .NET - .NET is Microsoft's closed-source Windows-only implementation of the CLR and other technologies, including various other framework libraries which aren't all covered in the above projects (which may themselves have libraries which aren't in .NET-proper). They do, however, allow you to write programs in C# and run them.
Yes - if you have a managed application, it will require the framework to be present in order to run. This is like requiring the Win32 libraries to be present in order to run Windows applications. Pre-compiling your code using ngen doesn't affect this requirement.
Having said the above, there are products which build everything you need from the framework for your application, along with your application itself, into one big bundle:
Both of these mean the framework itself isn't required, and give additional protection against decompilation. The downside is that if a user then has many such applications, they end up effectively with multiple copies of bits of the framework. They also mean that the user won't benefit immediately from updates such as service packs - they'd need a new version of your application. I cannot vouch for either of these products myself, as I've had no experience of them.
There are many abbreviations in .NET and related technologies. They're often abused, including by me, almost always unknowingly. Don't be too worried about them.
There are two versions of the C# specification - one from Microsoft, and one from ECMA. They are the same in all important respects as far as I can tell (a few pieces of explanatory wording are different, but nothing that affects the specification itself) but the numbering of sections is different.
The ECMA specification is available as a PDF, or you can email ECMA and they will send you a hard copy for free. Details are on the ECMA website. Alternatively, Jon Jagger's HTML version is available and is a useful download. It is from a draft version, but it's very close to the final version. I don't know whether or not Jon Jagger is planning to make an HTML copy of version 2 of the specification when it's released.
The Microsoft version is available online or within the offline version of the MSDN - look for "specifications, Visual C#" in the index to find it quickly.
The choice between C# and VB.NET is largely one of subjective
preference. Some people like C#'s terse syntax, others like VB.NET's
natural language, case-insensitive approach. Both have access to the same
framework libraries. Both will perform largely equivalently (with a few
small differences which are unlikely to affect most people, assuming
VB.NET is used with Option Strict on). Learning the .NET framework itself is
a much bigger issue than learning either of the languages, and it's perfectly possible
to become fluent in both - so don't worry too much about which to plump for. There are,
however, a few actual differences which may affect your decision:
Option Strict off - type safety at compile time
goes out of the window, but legacy libraries which don't have strongly typed interfaces
become easier to use.
Microsoft.VisualBasic namespace, and can be
used by other languages with a reference to the Microsoft.VisualBasic.dll). Many of
these can be harmful to performance if used unwisely, however, and many people believe they should
be avoided for the most part. Some methods here are apparently faster than the more idiomatic
.NET equivalent, however. Readability should be considered: using VB functions probably makes the
code easier for a VB-classic programmer to read, but harder for someone from a background in another
.NET language to read.
Catch ... When ... clauses, which allow exceptions to be filtered based on runtime expressions
rather than just by type.
using statement, which makes unmanaged resource disposal simple.
(Available in VB.NET with Visual Studio 2005.)
Despite the fact that the above list appears to favour VB.NET, many people (myself included) prefer C#'s terse syntax enough to make them use C# instead.
Many people, including myself and the C# language designers, believe that 'with' often harms readability, and is more of a curse than a blessing. For more information, see the Ask a C# Language Designer page.
C# (and .NET in general) has multiple inheritance of interface (meaning that you can implement many interfaces in a type) but only single inheritance of implementation (meaning that you can only derive a class from one other class - which may, itself derive from another, etc). (I'll get round to the actual reasoning behind this sooner or later...)
C# doesn't have macros as such, nor does it strictly speaking have a pre-processor, but it does have conditional compilation symbols which can be used to affect compilation. These can be defined within code or with parameters to the compiler. The "pre-processing" directives in C# (named solely for consistency with C/C++, despite there being no separate pre-processing step) are (text taken from the ECMA specification):
#define and #undef#if, #elif, #else and #endif#line#error and #warning#region and #endregion
See section 9.5 of the ECMA specification for more information on the above. Conditional
compilation can also be achieved using the Conditional attribute on
a method, so that calls to the method will only be compiled when the appropriate
symbol is defined. See section 24.4.2 of the ECMA specifcation for more information on this.
Although C# doesn't have templates, and isn't likely to get them, it does (as version 2.0, in Visual Studio 2005) have a feature called generics. Generics provide a lot of the functionality of C++ templates (mostly in terms of type safety) but in a more restricted (and therefore potentially less confusing) way.
By default, all parameters are passed by value in C# - but you need to be aware that when you're passing a reference type, you're passing a reference rather than an actual object. For more information, see my article on parameter passing.
No, constructors are not inherited. For more information about constructors and constructor chaining, see my article on constructors.
You use : base (parameters) or : this (parameters) just before the
actual code for the constructor, depending on whether you want to call a constructor in the base class
or in this class. For more information about constructor chaining,
see my article on constructors.
A string literal such as @"c:\Foo" is called a verbatim string literal. It basically means,
"don't apply any interpretations to characters until the next quote character is reached". So, a verbatim
string literal can contain backslashes (without them being doubled-up) and even line separators. To get a
double-quote (") within a verbatim literal, you need to just double it, e.g.
@"My name is ""Jon""" represents the string My name is "Jon". Verbatim string literals
which contain line separators will also contain the white-space at the start of the line, so I tend
not to use them in cases where the white-space matters. They're very handy for including XML or SQL in your source
code though, and another typical use (which doesn't need line separators) is for specifying a path.
When @ appears before an identifier (the name of a variable, property, method etc), it indicates that the compiler should treat what follows as an identifier, even if it normally means something else. For instance, this code fails to compile:
int this = 42; // 'this' is a reserved word |
but this code compiles successfully:
int @this = 42;
|
C# defines the following character escape sequences:
\' - single quote, needed for character literals\" - double quote, needed for string literals\\ - backslash\0 - Unicode character 0\a - Alert (character 7)\b - Backspace (character 8)\f - Form feed (character 12)\n - New line (character 10)\r - Carriage return (character 13)\t - Horizontal tab (character 9)\v - Vertical quote (character 11)\uxxxx - Unicode escape sequence for character with hex value xxxx\xn[n][n][n] - Unicode escape sequence for character with hex value nnnn (variable length version of \uxxxx)\Uxxxxxxxx - Unicode escape sequence for character with hex value xxxxxxxx (for generating surrogates)
Of these, \a, \f, \v, \x and \U are rarely used in my experience.
static and const together?
All constants declarations are implicitly static, and the C# specification states that the
(redundant) inclusion of the static modifier is prohibited. I believe this is to avoid the
confusion which could occur if a reader were to see two constants, one declared static and one not - they
could easily assume that the difference in specification implied a difference in semantics. (Having said
that, there is no prohibition on redundantly specifying an access modifier which is also the default one,
where there is a choice. For instance, a (concrete) method can be explicitly marked as private despite that being the
default. The rule appears to be that where there is no choice (e.g. a method declaration in an interface)
the redundant modifier is prohibited. Where there is a choice, it's allowed.
Put simply, an event gives more limited access than a delegate. If an event is made public, code in other classes can only add or remove handlers for that event; they can't necessarily fire it, find out all the handlers for it, or remove handlers they don't know about. Events also allow more flexibility in terms of how the handlers are stored. For more details on this, see Eric Gunnerson's article on the topic.
string and System.String?
C# defines a number of aliases for CLR types. They may be used interchangably, and even mixed together, e.g.
string x = new System.String(' ', 5);. These are the aliases defined:
| Alias | CLR type |
|---|---|
| string | System.String |
| sbyte | System.SByte |
| byte | System.Byte |
| short | System.Int16 |
| ushort | System.UInt16 |
| int | System.Int32 |
| uint | System.UInt32 |
| long | System.Int64 |
| ulong | System.UInt64 |
| char | System.Char |
| float | System.Single |
| double | System.Double |
| bool | System.Boolean |
| decimal | System.Decimal |
You can't in C# prior to 2.0, but fortunately this restriction was lifted in 2.0.
override and new?This is all to do with polymorphism. When a virtual method is called on a reference, the actual type of the object that the reference refers to is used to decide which method implementation to use. When a method of a base class is overridden in a derived class, the version in the derived class is used, even if the calling code didn't "know" that the object was an instance of the derived class. For instance:
public class Base { public virtual void SomeMethod() { } } public class Derived : Base { public override void SomeMethod() { } } ... Base b = new Derived(); b.SomeMethod(); |
will end up calling Derived.SomeMethod if that overrides Base.SomeMethod. Now,
if you use the new keyword instead of override, the method in the derived class
doesn't override the method in the base class, it merely hides it. In that case, code like this:
public class Base { public virtual void SomeOtherMethod() { } } public class Derived : Base { public new void SomeOtherMethod() { } } ... Base b = new Derived(); Derived d = new Derived(); b.SomeOtherMethod(); d.SomeOtherMethod(); |
Will first call Base.SomeOtherMethod (line 3), then Derived.SomeOtherMethod (line 4).
They're effectively two entirely separate methods which happen to have the same name, rather than the derived method
overriding the base method.
If you don't specify either new or overrides, the resulting output is the same
as if you specified new, but you'll also get a compiler warning (as you may not be aware that you're
hiding a method in the base class method, or indeed you may have wanted to override it, and merely forgot to
include the keyword).
That provides the basics of overriding and the difference between new and override,
but you should really see a book or tutorial for a more in-depth look at polymorphism.
What you need is reflection. The basic idea is that you find the type which contains the method, find the method from that type, and then invoke it. Here's a sample program - it's simple (it doesn't pass any parameters, it only finds a public method, it doesn't use a return value) but it gives the basic idea. Look up the relevant methods in MSDN for more information.
using System; using System.Reflection; class Test { string name; Test (string name) { this.name = name; } public void ShowName() { Console.WriteLine(name); } static void Main() { // Create an instance of Test Test t = new Test ("Foo"); // Get the method we want to call MethodInfo mi = typeof(Test).GetMethod("ShowName"); // Call it on the instance we've created, // with no arguments mi.Invoke (t, null); } } |
as operator?
Using the as operator differs from a cast in C# in three important ways:
as will not perform user-defined conversions, such as implicit or
explicit conversion operators, which casting syntax will do.
There are in fact two completely different operations defined in IL that
handle these two keywords (the castclass and isinst instructions) - it's not
just "syntactic sugar" written by C# to get this different behavior. The
as operator appears to be slightly faster in v1.0 and v1.1 of Microsoft's
CLR compared to casting (even in cases where there are no invalid casts
which would severely lower casting's performance due to exceptions).
Use the using directive to create an alias for a long namespace or class.
You can then use it anywhere you normally would have used that class or
namespace. The using alias has a scope within the namespace you declare it in. Sample code:
// Namespace: using act = System.Runtime.Remoting.Activation; // Class: using list = System.Collections.ArrayList; ... list l = new list(); // Creates an ArrayList act.UrlAttribute foo; // Equivalent to System.Runtime.Remoting.Activation.UrlAttribute foo |
Checked exceptions are a very hotly debated topic in some circles, particularly for experienced Java developers moving to, or additionally learning, C#. Here are some resources that discuss the issue in depth:
Note that without the CLR itself supporting checked exceptions, it would be effectively impossible for C# to do so alone.
The .NET runtime can't guarantee that parameterless constructors will be called. If structs where to allow default, parameterless constructors, it would imply that these default constructors would *always* be called. However, the runtime can not make this guarantee. For example an array of value types will be initialized to the initial values of its members (i.e. 0 for number type primitive members, null for reference types etc) not to the values provided in a default constructor - which makes structs better performing by not having to call constructor code. Enforcing a minimum of one parameter in the constructor reduces the possibility that someone will define a constructor that they then expect to be called every time one of their struct types is constructed.
If you need to tell C# that you want it to treat a literal as a particular type of number, you may do so by adding a number type suffix at the end of the literal you provide. For example:
1U; // An unsigned int 1ul; // An unsigned long 1f; // A System.Single floating-point number; 1d; // A System.Double floating-point number 1m; // a System.Decimal floating-point number |
This is somewhat important because sometimes you must match a literal to the
signature of something or specify the value to 'defeat' an implicit cast
behavior you don't like. For example, Hashtable names = new Hashtable(100, 0.1);
won't compile because the constructor takes parameters (int, float) and the above is
(int, double). The line should read Hashtable names = new Hashtable(100, 0.1f);
A full listing of the suffixes is in the Grammar portion of the C# specification (appendix A in the ECMA specification, appendix C in the MS specification). The suffixes are also detailed in the Literals section of the specification (9.4.4 of the ECMA specification, 2.4.4 of the MS specification).
Both the ref and out modifiers are applied to arguments of a method
and both mean that the argument will be passed "by reference" (either a
value type variable by reference or a reference type variable by reference).
The out parameter, however, allows you to pass in an uninitialized variable
like so and guarantees it will come back with its value set (so long as the
called method was written in C#, anyway).
int i; DoStuffByRef(out i); // i is now a usable int value |
For more details, see my article on parameter passing.
Equals and when should I use ==?
The Equals method is just a virtual one defined in System.Object, and overridden
by whichever classes choose to do so. The == operator is an operator which can be overloaded
by classes, but which usually has identity behaviour.
For reference types where == has not been overloaded, it compares whether two references
refer to the same object - which is exactly what the implementation of Equals does in
System.Object.
Value types do not provide an overload for == by default.
However, most of the value types provided by the framework provide their
own overload. The default implementation of Equals for a value
type is provided by ValueType, and uses reflection
to make the comparison, which makes it significantly slower than a
type-specific implementation normally would be. This implementation also
calls Equals on pairs of references within the two values
being compared.
However, the main difference between the two types of comparison in normal use (where you're unlikely to be defining your own value types very often) is polymorphism. Operators are overloaded, not overridden, which means that unless the compiler knows to call the more specific version, it'll just call the identity version. To illustrate that, here's an example:
using System; public class Test { static void Main() { // Create two equal but distinct strings string a = new string(new char[] {'h', 'e', 'l', 'l', 'o'}); string b = new string(new char[] {'h', 'e', 'l', 'l', 'o'}); Console.WriteLine (a==b); Console.WriteLine (a.Equals(b)); // Now let's see what happens with the same tests but // with variables of type object object c = a; object d = b; Console.WriteLine (c==d); Console.WriteLine (c.Equals(d)); } } |
The results are:
True True False True |
The third line is False because the compiler can only call the non-overloaded version of ==
as it doesn't know that the contents of c and d are both string references. As they
are references to different strings, the identity operator returns false.
So, when should you use which operator? My rule of thumb is that for almost all reference types, use Equals
when you want to test equality rather than reference identity. The exception is for strings - comparing strings with
== does make things an awful lot simpler and more readable but you need to remember that both
sides of the operator must be expressions of type string in order to get the comparison to work properly.
For value types, I'd normally use == for easier-to-read code. Things would get tricky if a value type
provided an overload for == which acted differently to Equals, but I'd consider such a type
very badly designed to start with.
Nothing?
For reference types, the equivalent of VB's Nothing is C#'s null.
For value types, it's the default value - 0, false, etc.
Use String.Substring. Assuming that x is a string of length at least
n, to get the last n characters, you would use x.Substring(x.Length-n).
addressof?
To create delegate instances in C#, you just specify the delegate type, the method, and (if
you want to create a delegate targetting a different instance or type from the current one) the target.
For instance, each of these creates a ThreadStart delegate:
ThreadStart x1 = new ThreadStart(SomeInstanceMethod); ThreadStart x2 = new ThreadStart(AnotherType.SomeStaticMethod); ThreadStart x3 = new ThreadStart(someVariable.SomeInstanceMethod); |
MyClass?
No, C# doesn't have an equivalent of VB.NET's MyClass keyword. If you want to guarantee
not to call an overridden version of a method, you need to make it non-virtual in the first place.
Me and MyBase?
Me in C# is this, and MyBase in C# is base. To access
normal members, just use this.memberName or base.memberName. For information
about chaining constructors together, see my
article on constructors.
Microsoft provides a very full language equivalents page which compares not only C# and VB.NET, but also other languages targeted at the .NET framework. It looks at the equivalent concepts, keywords, types, operators etc. A very valuable resource when you're trying to read or write code in a language which isn't your preferred one.
You need to use the Process.Start method. You can build more complicated
start-up parameters using the ProcessStartInfo class which allows you to
specify command line parameters, redirect output etc. The ProcessStartInfo and Process
classes are in the System.Diagnostics namespace.
Probably the best way of accomplishing this is using a named mutex. Create the mutex using code such as:
bool firstInstance; Mutex mutex = new Mutex(false, "Local\\"+someUniqueName, out firstInstance); // If firstInstance is now true, we're the first instance of the application; // otherwise another instance is running. |
Note that the mutex is a local one, which means it's in the current user's session - without the local part, other users would share the mutex, so two different users couldn't run the program at the same time. Also note that (unlike various samples around the net) my code doesn't have a call to ReleaseMutex - this is because the mutex will automatically be released when the process dies, which is usually the desired behaviour anyway.
One thing to beware of is that the mutex isn't garbage collected. If a local variable is only used
near the start of a method, the GC may ignore it when working out which variables are garbage collection
"roots" if that part of the method has already been executed. This can lead to the mutex being
released earlier than you might anticipate! To prevent this from happening, make a call to
GC.KeepAlive(mutex); at the end of your main method. Alternatively, use a static variable
to store the mutex. That will ensure that the mutex is not garbage collected until the AppDomain
is unloaded. (That way even if Main terminates, you won't have any problems if you've
got other threads running.)
Another way of attacking the problem (which comes with its own issues) is to listen on a local port. As only one process can listen on any particular port, that can ensure that no other instance of your application is running. However, it could just be that another application wants to use that port, in which case either your application will think there's another instance running, or the other application is likely to malfunction. Note that this approach has the added benefit that it provides a communication channel between the "main" instance and the newly created instance - if, say, the newly created instance wants to tell the main instance to open a file that the user has just requested, it can do so using the socket.
Whenever text is stored in a file, or sent across a network, it is always encoded in some way or other, to convert the characters into bytes. It then needs to be decoded to get the characters back again. If you use the wrong encoding, you (naturally) get the wrong results. This is usually the cause of a failure to see "extended" characters. It's a big topic, so see my article on Unicode for more information.
.NET doesn't get arithmetic wrong, as such - it just does arithmetic in a different way to how you might expect. For instance, when you write 0.1 in code to be stored in a double variable, the value stored isn't actually 0.1. It's as close to 0.1 as can be represented in the double type, but it's not actually 0.1. This is because the float/double types are binary floating point types, and 0.1 (decimal) can't be exactly represented in base 2.
For more information on this, see my article on .NET floating point types.
The Convert class has an overload of the static ToString() method that takes
two ints and returns a string populated with the number in the specified base. For instance, calling
Convert.ToString(128, 2) will return "10000000".
Initialize() on a reference-type array fill the
array with objects?
The System.Array class instance method Initialize() exists solely to
initialize value type arrays to their default values and is not valid on
reference type arrays. (In fact it is not even intended for C# value type
structs, as these structs can have no default constructor for Initialize to
call. CLR value types are allowed to have parameterless constructors, but there's no
way of creating such a type in C#.)
In version 1.1, the .NET framework doesn't contain any general purpose compression libraries, but there are plenty
of third-party libraries available. The most commonly referenced is probably
SharpZipLib, which is
free and open source but may still be used in commercial applications. Version 2.0 of the framework contains
some compression (see the System.IO.Compression namespace) but does not include support
for zip files themselves.
Most of the assembly-wide attributes (which are usually specified in AssemblyInfo.cs) are
available using Assembly.GetCustomAttributes. For instance, to get the assembly title,
you could use code such as:
Assembly thisAsm = this.GetType().Assembly; object[] attrs = thisAsm.GetCustomAttributes(typeof(AssemblyTitleAttribute), false)); if (attrs.Length == 1) { Console.WriteLine(((AssemblyTitleAttribute)attrs[0]).Title); } |
Note, however, that AssemblyVersionAttribute ends up as just part of the assembly name,
which can be retrieved with the Assembly.GetName method. The version can be retrieved from
the name with the Version property. For example:
Assembly thisAsm = this.GetType().Assembly;
Console.WriteLine (thisAsm.GetName().Version);
|
string to an int etc?
In general, when you want to convert from one type to another, the
first class to look at is System.Convert. It has a load of
static methods which are likely to help you. If you're converting from a
String, you could also check whether the type that you want
to convert to has a DateTime.ParseExact to convert from
a String to a DateTime.
Convert.ToInt32(string) and Int32.Parse(string)?
The two give identical results, except where the string is null. Convert.ToInt32(null)
returns zero, whereas Int32.Parse(null) throws an ArgumentNullException.
This is a two stage process. Firstly, you need to get a Type reference for the type. If the type
you want to create an instance of is in either mscorlib or the current assembly, you can just
use Type.GetType(name). If it's in a different assemby, you could either call Type.GetType
and pass in the full type name including assembly information, or you could find or load the assemnbly and then
call Assembly.GetType(name) on that assembly reference.
Once you've got a Type reference, you can either use Activator.CreateInstance(type) to
create an instance, or call Type.GetConstructor to get a specific constructor which you can then
use to create an instance by calling Invoke on it.
For a good mixture of flexibility and ease of use, the System.Net.WebRequest class is a good way
of retrieving web content. Some very simple code is given below, but there are many options available
including asynchronous downloads and lots of properties to both set and retrieve for the request and
response. For some very simple scenarios, System.Net.WebClient is an alternative providing
limited but very easy to use functionality.
using System.Net; using System.IO; using System.Text; ... string url = "http://www.microsoft.com"; WebRequest req = WebRequest.Create(url); // If the URL is an HTTP one, you can cast req to // HttpWebRequest, which allows you to set // more properties, such as the user agent. // Similarly, a response to an HTTP request can be // cast to HttpWebResponse. using (WebResponse resp = req.GetResponse()) { // Make sure you use the right encoding - // if you don't know it in advance, you should // look at the response to see what the web server // says it is. For binary content, you'd // want to use the stream directly instead // of wrapping it in a StreamReader. using (StreamReader reader = new StreamReader (resp.GetResponseStream(), Encoding.UTF8)) { string content = reader.ReadToEnd(); // Do whatever you want with the content here } } |
Forms are just objects like any other. To call a method or pass a parameter from one form to another, you need to have a reference to the "target" form in the "source" form, and the method/property/whatever of the "target" form needs to be accessible (which usually means at least "internal" visibility).
Part of this answer is specific to .NET 1.1 and earlier. In .NET 2.0 the BackgroundImage property works.
BackColor needs to be set according to the code below.
The area of an MDI container window is covered by an MdiClient control,
so Form.BackColor and Form.BackgroundImage don't do anything useful.
Instead, iterate through the controls to find the MdiClient, like this:
private void Form_Load(object sender, System.EventArgs e) { foreach (Control ctl in this.Controls) { if (ctl is MdiClient) // found it { ctl.BackColor = Color.Yellow; break; } } } |
If you need to update the MDI background when the window is resized - to keep a logo in the centre,
for example - you must handle the Paint event for the MdiClient.
Import the SetClipboardViewer API function, and call it in your initialisation code,
passing the handle of your form. The form will then receive WM_DRAWCLIPBOARD messages,
which you can handle in WndProc.
using System.Runtime.InteropServices; ... [DllImport("user32.dll")] public static extern int SetClipboardViewer(int hWnd); private const int WM_DRAWCLIPBOARD = 776; // ... somewhere in initialisation code ... SetClipboardViewer(this.Handle.ToInt32()); protected override void WndProc(ref Message m) { // Process the message normally base.WndProc(ref m); if (m.Msg == WM_DRAWCLIPBOARD) { // ... respond to Clipboard changes ... } } |
Dispose or Close?
As far as I can tell, the only difference between calling Close and Dispose on database
connections should be that Close leaves the connection in a reusable but closed state - you can
still access all the properties, etc, and even call Open again. As with any object, after calling
Dispose on a database connection, you shouldn't access it any further.
This does not mean that calling Dispose removes the connection from the connection pool, however.
There is a sort of urban myth that it does, and that you should therefore only call Close on connections,
and not Dispose. Fortunately, it's untrue according to tests I've performed. I say "fortunately" because
it lends consistency to the framework - basically, you should always be able to call Dispose on an instnace
of any type implementing IDisposable without suffering from problems - it should (in my view) be considered
the "default" way of releasing non-memory resources. This is supported by the C# "using" statement which makes it so
easy to automatically call Dispose. Just as I never call Close on a Stream, I
never call Close on a database connection unless I specifically want to reuse it later.
The answer here is not to put the data in your SQL statements at all, but to use parameters. Every data provider
worth using provides a way of specifying parameters in SQL statements, either named (e.g.
SELECT NAME FROM PEOPLE WHERE ID=@ID) or positional (e.g. SELECT NAME FROM PEOPLE WHERE ID=?).
Some providers only support positional parameters, others only support named parameters, others support both. In practice
it's not hard to work in a consistent way with either, by always using sensible names and always specifying the command's
parameters in the same order that they appear in the SQL statement.
Parameters are basically a mechanism for having a single SQL statement which can take different values for some parts.
You use a SqlCommand (or the equivalent for your database provider) to specify the query text, the type of
the command (stored procedure, text, etc) and the parameters. You set the command up with parameters once, and then
you can use the command several times, having set the parameter values up with the relevant data for each request.
If you're using a DataAdapter to update your database, the parameter values for the relevant command
(update, insert or delete) are filled in automatically, assuming you've set the parameters up correctly.
Parameters allow you to write your SQL without worrying about escaping values or formatting dates and times etc. The database provider will do all that (assuming it even needs to). You don't need to worry about SQL injection attacks - whatever parameter value you specify, it won't be used as SQL itself. Parameters also make life easier for the database - it can cache the query you've provided it so that it doesn't need to do as much work on future requests - it knows everything apart from the actual parameter values already. In short, parameters are wonderful things, and should be used whenever you've got values which may change for different requests. It even makes life easier if you're always going to use the same value, if that value is anything complicated (like a string which may require escaping, or a date and time which requires formatting).
For more information about using parameters in database access, see the documentation for whichever database provider
you're using. The command type for your provider is likely to have a Parameters property which is a good
starting point for finding out more.
Many people have intellectual property concerns about .NET, because it's easy to decompile IL into C# or VB.NET, and the code produced is often remarkably similar to the original source. Personally I feel that most of the time these concerns are misplaced. If your application becomes sufficiently popular that people are decompiling it, chances are you're making significant money from it anyway. If you're worried about your algorithsm themselves being poached, I believe that the overall design of an application or architecture is usually more valuable than a specific algorithm. If you're concerned about the security of private keys (or whatever) which are in your code, you're relying on security through obscurity to start with, which is never a good idea.
Valid IL can always be decompiled to some extent, and modifying it so that it's no longer the kind of IL which is "naturally" produced by the C# or VB.NET compilers is likely to have a negative performance impact as the JIT will have been tailored towards the output of those compilers. However, you can go a long way by using an obfuscator. Obfuscators change the names in code (where possible) so that lumps of code become a lot less meaningful. For most sufficiently large apps, I believe this to be "good enough" protection as understanding a large app with no source documentation is hard enough originally, let alone with mangled names. One possible exception to this is licence-handling code - if someone can work out which part of your code is responsible for checking that the installation is licensed, it may well be simple for them to disable it. Of course, with a large program with type names which are no longer readable, it may not always be easy to do this in the first place...
RemoteSoft's linker (see an earlier question) provides more protection than a normal obfuscator, as the IL is no longer present. (This is in contrst to ngen, which precompiles the code but still maintains the IL.) Note that even this is only going to increase the protection rather than giving absolute protection though - if someone has your code and can run it, they can work out how it does what it does, given enough time and patience. This has always been true, and gives one of the benefits of server-side code, where the user never actually has your code at all, only the results of specific requests etc.
There are many obfuscators around, some free and some commercial. VS.NET 2003 comes with the community version of Dotfuscator. See the .NET tools list on MSDN for other options. I don't have any experience of Dotfuscator or any other .NET obfuscators.
No particular recommendations here - this is just a list of what's around.
No particular recommendations here - this is just a list of what's around.
This is of course a highly subjective matter, so the name of the recommendation is provided along with the recommendation itself - you may find you have the same taste as a particular person, and wish to "trust" their recommendations more than those provided by some other people.