ASP.NET Basics (part 2): Not My Type

Learn about ASP.NET variables and data types.

Getting Serious

In the first part of this article, I introduced you to .NET and got you started with ASP.NET and the .NET Framework with some simple examples and explanations. I discussed the anatomy of an ASP.NET program, offered a brief introduction to the cool whizbangs that are server controls, and told you some basic things about C# variables.

Now, if you're ever going to do anything serious with ASP.NET, you need to make sure you've got the basics down. And you can't get more basic than variables - they're the cogs that make the motor tick, the plinth on which the building rests, the runes from whence all power flows, the...I could go on, but I won't. Instead, I'll simply tell you that variables are, to put it mildly, fairly important, and mastering them is an important part of your ASP.NET learning experience. Which is why this segment of the tutorial focuses entirely on variables - what they are, how they work, what you can do with them, and which flavours they come in. Flip the page, and let's get this show on the road!

Building Blocks

Let's start with the basics: what's a variable when it's home curled up on the couch?

A variable is the fundamental building block of any programming languages. Think of a variable as a container which can be used to store data; this data is used in different places in your ASP.NET program. A variable can store both numeric and non-numeric data, and the contents of a variable can be altered during program execution. Finally, variables can be compared with each other, and you - the programmer - can write program code that performs specific actions on the basis of this comparison.

Every variable must have a name - this name is used to refer to the variable, to perform operations on it, and to retrieve the data it contains. In C#, a variable name is preceded by a keyword indicating the variable type, and must begin with a letter, optionally followed by more letters and numbers. Variable names are case-sensitive, and reserved keywords cannot be used as variable names. For example, "popeye", "one_two_three" and "bigPirateShip" are all valid variable names, while "byte" and "123" are invalid variable names.

Every language has different types of variables - and ASP.NET and C# display no shortage of choices. C# supports a wide variety of data types, including simple numeric, character, string and Boolean types, and more complex arrays, structures, enumerations, classes and interfaces. Over the course of the next few pages, I'll be looking

A New Assignment

Now, you might not know this, but you've already seen the "string" data type in action. In the first part of this tutorial, I used the following script to introduce you to variables.

<script language="c#" runat="server">
void Page_Load()
{
    string name;    // define a variable as a string type
    name = "Neo";   // put some initial value into it
    whoami.Text = "I am " + name + ". Welcome to my world.";
}
</script>
<html>
<head><title>Who am I?</title></head>
<body>
<asp:label id="whoami" runat="server" />
</body>
</html>

In this example, the variable "name" has been defined as a string, and stores the string value "Neo". As you will see, a similar technique can be used to define other types of variables also.

There are two important operators in this example that I "conveniently" forgot to mention when I first introduced it. Now that my memory is fully restored, though, let me bring them to your attention. The first is the assignment operator, as illustrated in the snippet below:

<%
name = "Neo";   // put some initial value into it
%>

The assignment operator in C# scripts, like in most other languages, is the = symbol, and it's used to assign a value (the right side of the equation) to a variable (the left side). The value being assigned need not always be fixed; it could also be another variable,

<%
name = myname;
%>

or an expression,

<%
sum = (10 * 2) + (20 / 5);
%>

or even an expression involving other variables

<%
diff = temp - 20;
%>

The assignment operator will be a staple of your C# experience - nary a day will pass when you don't use it - so get used to seeing it around.

So that takes care of the first operator - now for the second:

<%
whoami.Text = "I am " + name + ". Welcome to my world.";
%>

You'll notice that this line of code combines three strings to form a single string. This is accomplished by using the concatenation (+) operator, whose primary job is to add strings together. You can also use it to add numbers - I'll show you that shortly.

Strange Characters

A close relative of the "string" data type is the "char" data type. As you might have guessed, this data type is used to store a single character (unlike the "string" type, which is used to store a sequence of characters). Take a look at the next example, which demonstrates how character variables work.

<script language="C#" runat="server">
void Page_Load()
{
    char saviour;   // define a character variable

    saviour = 'Q';  // assign a value

    answer.Text = "James Bond's favourite mad scientist is...<b>" + saviour +
"</b>";

}
</script>
<html>
<head><title>James Bond Trivia</title></head>
<body>
<asp:label id="answer" runat="server" /></b>
</body>
</html>

Here's the output.

No rocket science here: the "char" keyword is used to define a character variable,

<%
char saviour;   // define a character variable
%>

and the assignment operator is used to assign it a value.

<%
saviour = 'Q';  // assign a value
%>

If you have a sharp eye, you will notice that the initialization of a character variable is slightly different from that of a string variable - when initializing a character variable, you must use single quotes instead of double quotes, or else the program will barf and say the following:

Playing The Numbers

Some programming languages (like PHP and VBScript) do not offer a range of numeric variables to play with, preferring instead to use one catch-all type; others (like C++ and Java) are very fussy and insist on offering you specialized data types for different purposes. In case you're wondering, yes, C# falls in the latter category.

There are broadly three kinds of numeric data types in C#: integer, floating-point and decimal.

  1. Integers: These are plain-vanilla numbers like 23, 5748, -947 and 3; they are also the most commonly used type. Based on the range of the number being stored, the language has the following data types:
  • sbtye: stores a number between -127 to 127

  • short: stores a number between -32768 to 32767

  • int: stores a number between -2147483648 to -2147483647

  • long: stores a number between -9223372036854775808 to 9223372036854775807

  • byte: stores a number between 0 to 255

  • ushort: stores a number between 0 and 65535

  • uint: stores a number between 0 and 4294967295

  • ulong: stores a number between 0 and 18446744073709551615

The first four data types are often referred to as "signed" integers while the last four are referred to as "unsigned" integers. This has to do with the fact that first bit for the signed integer data types is used to store information about which side of the number line the integer lies on (0 for positive integers, 1 for negative integers). Unsigned data types assume that their values are always positive (and use the extra bit to offer a wider range of storage).

  1. Floating-points: These are typically fractional numbers such as 12.5 or 3.149391239129. There are two floating-point data types.
  • float: stores a number between +/- 1.5 X 10-45 to +/- 3.4 X 1038

  • double: stores a number between +/- 5.0 X 10-324 to +/- 1.7 X 10308

The main difference between the two types is in the "precision", or the number of significant figures after the decimal. If you want 7 or fewer significant digits after the decimal point (32-bit precision), use a "float"; if you want between 8 and 16 significant digits after the decimal point (64-bit precision), use a "double".

  1. Decimals: The "decimal" data type should be used when you require a high level of precision, since it can accurately store data up to 28 digits after the decimal points (128-bit precision).

Operate With Caution

You'll remember how, in the first part of this tutorial, I used the + operator to add strings together. And just as you have the + operator for concatenating strings, C# comes with a bunch of other arithmetic operators designed to simplify the task of performing mathematical operations.

The following example demonstrates the important arithmetic operators available in C#:

<script language="C#" runat="server">
void Page_Load()
{
    // define some numeric variables
    int alpha, beta;

    // and some more
    int sum, difference, product, quotient;

    // initialize them
    alpha = 69;
    beta = 96;

    sum = alpha + beta;             // addition
    difference = beta - alpha;      // subtraction
    product = alpha * beta;         // multiplication
    quotient = beta / alpha;        // integer division

    addition.Text = "Sum of " + alpha + " and  " + beta + " is " + sum + ".";
    subtraction.Text = "Difference of " + beta + " and " + alpha + " is " + difference + ".";
    multiplication.Text = "Product of " + alpha + " and " + beta + " is " + product + ".";
    division.Text = "Quotient of " + beta + " by " + alpha + " is " + quotient + ".";

}
</script>
<html>
<head><title>Math Class</title></head>
<body>
<asp:label id="addition" runat="server" /><br />
<asp:label id="subtraction" runat="server" /><br />
<asp:label id="multiplication" runat="server" /><br />
<asp:label id="division" runat="server" /><br />
</body>
</html>

And here is the output:

As with all other programming languages, division and multiplication take precedence over addition and subtraction, although parentheses can be used to give a particular operation greater precedence. For example, the following statement

<%
result = 10 + 2 * 4;
%>

will store 18 in "result", while

<%
result = ((10 + 2) * 4);
%>

assigns 48 to the variable.

In addition to these operators, C# comes with the very useful auto-increment (++) and auto-decrement (--) operators, which you'll see a lot of in forthcoming articles. The auto-increment operator increments the value of the variable by 1. The auto-decrement operator does the opposite. Here's an example which illustrates how this works

<script language="C#" runat="server">
void Page_Load()
{
    // define a variable
    int x=99;

    x++;
    // now x = 100

    x--;
    // now x = 99
}
</script>

Everything Must Go

In the last few sections, I introduced various numeric data types along with the common arithmetic operations that may be performed on them. As you've seen, this is all fine and dandy so long as you're dealing with data of the same type - but what happens when the day arrives (and it will, make no mistake about that) that you want to mix and match data of different types?

That's a very logical question, and it comes with an interesting answer. In order to respond, I'm going to take you a quick diversion, into a world filled with advertisements for "car finance at a fabulous 0.99 APR" and "mega SALE - 24.66 % discount on all items". In this world, every transaction made undoubtedly has to deal with fractions and integers together.

How does C# handle such a situation? Let's take a look:

<script language="c#" runat="server">
void Page_Load()
{
    // price of item
    int price = 55;

    // discount on item
    int discountrate = 24;

    // number of items purchased
    int numitems = 15;

    // discount amount on each item - should equal 13.2
    int discountamt = (price * discountrate) / 100;

    // grand total for all items - should equal 627
    int grandtotal = (price - discountamt) * numitems;

    // assign values to appropriate labels
    lblprice.Text = "" + price;
    lblnumitems.Text = "" + numitems;
    lbldiscountamt.Text= "" + discountamt;
    lblgrandtotal.Text = "" + grandtotal;

}
</script>
<html>
<head><title>The Mega Sale</title></head>
<body>
<table width="350" cellpadding="5" cellspacing="5" border="3">
<tr><td>Price of selected item:</td><td>$<asp:label id="lblprice"
runat="server" />.</td></tr>
<tr><td>Number of items purchased:</td><td> <asp:label id="lblnumitems"
runat="server" />.</td></tr>
<tr><td>Discount for each item:</td><td> $<asp:label id="lbldiscountamt"
runat="server" />.</td></tr>
<tr><td>Grand total for all items after discount:</td><td> $<asp:label
id="lblgrandtotal" runat="server" />.</td></tr>
</table>
</body>
</html>

In the script above, I have defined five variables:

  • "price", an integer to store the price of the selected item;

  • "discountrate", a integer to store the rate of discount on the item;

  • "numitems", a integer to store the number of items purchased;

  • "discountamt", a integer to store discount amount per item;

  • "grandtotal", an integer to store grand total for all items after discount;

Some basic mathematical calculations and bingo, I arrive at the total amount a customer has to pay after discount. To make things interesting, I have calculated the variable values manually as well; now to check them against the output of the script.

As you can see, there is a discrepancy between the manually-calculated amounts and the output of the script - the discount amount per item should be $13.2, though the output above shows it as $13. Correspondingly, the total amount should be $627, although the script shows it to be $630.

Why did this happen? Simple. In integer arithmetic, all fractional parts of any floating-point number are dropped or rounded off, leading to an incorrect value in the "discountamt" variable in the script above. As you can see, this has a cascading effect on all further calculations, giving rise to a hugely incorrect result (and quite a few angry calls to Customer Services as well).

This problem can be avoided by "casting" the variables appropriately. Casting is the process by which one data type is converted to another data type for the purpose of maintaining the integrity of the calculation. Let's take a closer look.

Cast And Credits

There are two kinds of casting supported by C# - "implicit casting" and "explicit casting".

Implicit casting means that the compiler will convert the variable from one data type to another data type on its own. However, this is possible only when the numeric range of the target type is greater than the numeric range of the source type.

Confused? Take a look at this next snippet:

<%
// price
short price = 1000;

// discounted price
int discountprice = price -  100;
%>

In this case, I have defined two variables of different data types - "short" and "int". The range of values that can be stored in the "price" variable ("short" data type) is a subset of the values that can be stored in the "discountprice" variable (of "int" data type). Therefore, when performing a mathematical operation like the one above, the compiler will carry out an implicit cast and convert the "price" variable into an integer.

How about the other way around?

<%
// price
int price = 1000;

// discounted price
short discountprice = price -  100;
%>

If you try running this, you'll see the following error:

You can view the possible combinations of implicit casting carried out by the .NET compiler at http://www.asia.cnet.com/builder/program/windows/0,39009376,39099752,00.htm

You've already seen implicit casting in this article, a few pages ago - although you might not have noticed it. Remember the following lines of code?

<%
intSbyte.Text = "" + varSbyte + "";
%>

By default, only a string can be assigned to the "Text" attribute of a "label" server control. Since "varSbyte" is an integer, it cannot be assigned directly; I first need to convert it into a string. The compiler will implicitly cast it into a string (and resolve the problem for me) if I concatenate it with any other string value....hence the string concatenation operations in the code above.

If this seems complicated to you - it is. Keep reading, I'll show you a simpler way to convert numbers to strings on the next page.

Now for explicit casting.

Explicit casting, as the name suggests, allows you to forcibly cast a variable from one data type to another. Here's a variant of a previous example that illustrates what I mean:

<%
// snip

    // discount amount on each item - should equal 13.2
    double discountamt = (double) (price * discountrate) / 100;

    // grand total for all items - should equal 627
    double grandtotal = (price - discountamt) * numitems;

%>

If you re-run the example with the changes above, this is what you'll see:

Now, the output shows correct values for the discount as well as the grand total. This is because I changed the data type of the "discountamt" and "grandtotal" variables to "double" so that they can store decimal values accurately. However, since "price" and "discountrate" are still integers, their product will also be an integer. Consequently, the division of this value by 100 will also be an integer value with the fractional part being lost. To avoid this loss, I have explicitly cast the result of the multiplication operation as a "double" - this will ensure that the correct decimal value (13.2) will be stored in "discountamt" instead of the incorrect integer value (13).

Mixing It Up

Thus far, I have only converted one numeric data type to another. How about converting a string to a number?

C# comes with an entire range of functions to convert a string to any other data type - here's a quick example that demonstrates:

<script language="c#" runat="server">
void Page_Load()
{

    // string to convert to number type
    string str= "123";

    // convert to a int integer
    int varInt = Convert.ToInt32(str);

    // set the labels
    strnumber.Text = str;
    intInt.Text = varInt.ToString();

}
</script>
<html>
<head><title>Strings At Play</title></head>
<body>
The string "<asp:label id="strnumber" runat="server" />"... converted to a
"int" <asp:label id="intInt" runat="server" />.<br />
</body>
</html>

And the output in the browser:

This isn't all - you can also convert a string to any other number type, using the following functions:

Convert.ToSByte(str) - convert str to a sbyte integer

Convert.ToInt16(str) - convert to a short integer variable

Convert.ToInt32(str) - convert to a regular integer variable

Convert.ToInt64(str) - convert to a long integer variable

Convert.ToByte(str) - convert to a byte integer variable

Convert.ToUInt16(str) - convert to an unsigned short integer variable

Convert.ToUInt32(str) - convert to a unsigned integer variable

Convert.ToUInt64(str) - convert to a unsigned long integer variable

What if the string can't be converted to a number, as in the following example?

<script language="c#" runat="server">
void Page_Load()
{

    // string to convert to number type
    string str= "abc";

    // convert to a int integer
    int varInt = Convert.ToInt32(str);

    // set the labels
    strnumber.Text = str;
    intInt.Text = varInt.ToString();

}
</script>
<html>
<head><title>Strings At Play</title></head>
<body>
The string "<asp:label id="strnumber" runat="server" />"... converted to a
"int" <asp:label id="intInt" runat="server" />.<br />
</body>
</html>

What will C# do?

You can also do the reverse - convert a number into a string - by means of the ToString() function, demonstrated below:

<%

// snip

// Set the labels
strnumber.Text = str;
intInt.Text = varInt.ToString();

// snip

%>

Cool, huh?

It's A Wrap

And that's about it for the moment. Over the last few pages, I delved into the murky waters of C# variables, explaining the numerous simple data types that are available in C#. Next, I dealt with the character, string and numeric data types and introduced the operators that are commonly used with them. The concept of casting - changing the type of a variable implicitly or explicitly - was also explained, as were the some of the C# functions related to data type conversion between strings and numbers.

Now that you know the basics of variables in C#, it's time to move on to the language's conditional statements. In the next article, I will explore the intricacies of conditional expressions, which come in very useful when adding control routines to your code, together with comparison and logical operators, whose sole raison d'etre is to evaluate expressions.

All that and more, next time...so see you then!

Note: Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!

This article was first published on 28 Jul 2003.