|
 Monday, January 29, 2007

The "as" Keyword

Last week I ran into a problem with the 'as' keyword in C#. For those of you who dont know, the "as" keyword works like this:

Lets say I have a variable and I'm certain its a string, but its in the form of an object (for whatever weird reason, perhaps you're getting it out of an ArrayList or something). I want to cast it to string. I can use the "as" keyword to do this.

string stuff = objectVariable as string;



So I had a problem this week when a co-worker wrote some code that did the following:

// Get variable from session
string myId = Session["objectKey"] as string;


Each time I accessed this variable (myId) it was null. WTF? I debugged for a second and I verfied that it was being set like so:

// Save Id for later
Session["objectKey"] = theIdToSave;


The variable "theIdToSave" was set to, lets say, a number, 5. Session saves everything as an object. The "as" keyword is a shorthand version of the tenary operator,  therefore...

string stuff = objectVariable as string;

//Is the same as

objectVariable is string ? (string)objectVariable : (string)null;


The problem was that we were putting a Int32 type into an object and trying to cast it to a string. This will only work if, and only if, it was of type string. Unfortunately it was not a string, it was of type Int32. Thefore, instead of raising an exception, the "as" keyword returns a null value. The type of the object in session can be verified by reflecting into the object by using the GetType method.

// This will return: {Name = "Int32" FullName = "System.Int32"}    
Session["Test"].GetType();

Keep in mind, when working with the "as" keyword in C#, be sure to know what types your working with. If you're trying to cast a variable to a type that it is not of, the "as" keyword will internally yield a null value instead of raising an exception.


#    Comments [0] |
 Wednesday, January 17, 2007

New Lines

Lines are represented differently in different operating systems. For most non Unix Platforms the new line is represented as: "\r\n" And for Unix Platforms the new line is represented as: "\n" I've found that most developers will hard code these values into their code, for example:

string someText = String.Format("This is a line1.{0} This is line 2.", @"\n");

That works, but there is a built in property in the .NET Framework to retrieve the current platforms New Line. This property is Environment.NewLine. Here's an example, using the same code above, but with Environment.NewLine in place of the hardcoded value.

string someText = String.Format("This is a line1.{0} This is line 2.", Environment.NewLine);

This property will return the new line string defined for the environment that the application is running in.

#    Comments [0] |
 Sunday, January 14, 2007

Escaping String Literals

I've been looking through a lot of "hand me down code" (code that was written awhile ago by someone else) that did a lot of File IO. The code works well, but at times its hard to read the really long file paths that they're using. As you know, file paths in C# have to be escaped, otherwise the compiler will think that you're trying to escape a character. So a double backslash actually equates to a single backslash when compiled. This can be cleaned up a bit. Read on brethern...

This is how the file paths look now:

// Current File Paths
string path = "c:\\directory\\folder1\\folder2\\folder3\\somefile.txt";

To make this cleaner, use the "@" symbol at the beginning of the string literal and it will escape the characters for you.

// New File Path
string path = @"c:\directory\folder1\folder2\folder3\somefile.txt";

Simple, but a lot of programmers dont know this little time saver.

NOTE: using the @ symbol when you need to included \t or \r, \n will not work. It will interepret the characters just as they are "\n" will print on the screen as "\n" not the new line that you're probably expecting.

#    Comments [0] |
 Wednesday, January 10, 2007

Warnings as Errors

Warning:
A: To give notice to beforehand especially of danger or evil
B: To give admonishing advice
C: To call to one's attention

With that said, we could infer that a warning is something that says "Hey, this is kind of important, you might want to watch this." To me, in .NET Development, a warning means I've done something wrong, I've created an error.

To ensure my builds are top notch, I have updated my projects to treat Warnings as Errors. This allows me to be notified of something immediately. If a warning occurs, its foresight into the future. Warning: "This is what could happen." Pretty much that means, you should probably fix that right now. Therefore I dont let builds complete if there are warnings in certain projects.

Here's how to do it...
  1. Go to the project properties and select the Build Tab.
  2. Select "All" under Treat Warnings as Errors



3. Save and build.

Now, lets say you have a variable thats created but not used in a method somewhere, you'd get an error screen like this:



The build will fail locally as well as on your build server.

This will help alleviate errors in the future that may be caused by something that was a warning two months ago. :)

You can also accomplish through the command line compiler:

csc.exe /warnaserror


This compiler switch will treat warnings as errors.

*Note: You might want to leave this option in its default state for projects where a warning is ommitted automatically, like set up projects that publish to a local system. This is something that I'm ok with as we publish it locally anyway.
#    Comments [0] |

ASP.NET File Name at Runtime

Retrieving the ASP.NET filename can be done in many ways. I've created this method in a few helper classes in some of the different jobs I have.

public string GetCurrentPageFileName()
{
   return new System.IO.FileInfo(Request.PhysicalPath).Name;
}

I've also created a base page class in the past to hold these types of methods (below).

/// <summary>
/// Base Page class
/// </summary>
public abstract class BasePage : System.Web.UI.Page
{
    protected string GetCurrentPageFileName()
    {
        return new System.IO.FileInfo(Request.PhysicalPath).Name;
    }
}

Throw this into the App_Code folder and change your default page implementation from System.Web.UI.Page to BasePage. You'll have all the same methods you did before, but this time with the extra methods. Add more functionality into the BasePage as necessary.

#    Comments [0] |
 Tuesday, January 09, 2007

Hiding Code From The Debugger

Sometimes there are methods in code that my development department knows are robust. There are no bugs in the code. This might be helper methods that have been tested time and time again. Therefore we know we dont need to debug these methods 99% of the time. To alleviate the pain of stepping through unnecessary lines of code accidentally you can inform the debugger that it is not suppossed to access a block of code. To do this add the DebuggerHidden Attribue. You cannot set a break point in this block of code when this attribute is present.

[DebuggerHidden]
void DoSomething()
{
// Do Something
}

*Note: This is only valid on constructors, methods, properties, and indexers only.

#    Comments [0] |
 Friday, January 05, 2007

Conditional Switch Statement with Enumeration String Value

As of recently I've had a few requests for how I handle a string representation of an Enumeration in a conditional switch. If you pass in a string into the switch statement without parsing the enumeration .NET will complain about a constant value being required. Here's how to write switch statement with a string respresentation of the Enumeration. You might find this useful when you store a string value of the enumeration in a data source such as a DB or XML File and you need to get its Enumeration value through code.

A lot of the time developers will get an error when they first attempt to peform a conditional switch without knowing how to do it. The error they get is "a constant value is required". Here's how to actually implement it. :)

 

public enum Product
{
    Word,
    Outlook,
    Excel
}

public void Process(string productName)
{
    switch ((Product)Enum.Parse(typeof(Product), productName.ToString()))
    {
        case Product.Excel:
        // Do something
            break;
        case Product.Outlook:
            // Do Something
            break;
        case Product.Word:
            // Do something
            break;            
    }        
}
#    Comments [0] |