Variables types, constants and objects
Variables
A variable is nothing but a name given to a storage area that our programs can manipulate. Each variable in C# has a specific type, which determines the size and layout of the variable’s memory; the range of values that can be stored within that memory; and the set of operations that can be applied to the variable.
A data type can be described as being either:
- A built-in data type, such as an int or char, or
- A user-defined data type, such as a class or interface.
- Data types can also be defined as being either:
- Value Types (C# Reference), which store values, or
- Reference Types (C# Reference), which store references to the actual data.
We have already discussed various data types. The basic value types provided in C# can be categorized as:
Type | Example |
---|---|
Integral types | sbyte, byte, short, ushort, int, uint, long, ulong and char |
Floating point types | float and double |
Decimal types | decimal |
Boolean types | true or false values, as assigned |
Nullable types | Nullable data types |
C# also allows defining other value types of variable like enum and reference types of variables like class, which we will cover in subsequent chapters. For this chapter, let us study only basic variable types.
Variable Declaration in C#
Syntax for variable declaration in C# is:
<data_type><variable_list>;
Here, data_type must be a valid C# data type including char, int, float, double, or any user defined data type etc., and variable_list may consist of one or more identifier names separated by commas.
Some valid variable declarations along with their definition are shown here:
int i, j, k;char c, ch;float f, salary;double d;
You can initialize a variable at the time of declaration as:
int i =100;
Variable Initialization in C#
Variables are initialized (assigned a value) with an equal sign followed by a constant expression. The general form of initialization is:
variable_name = value;
Variables can be initialized (assigned an initial value) in their declaration. The initializer consists of an equal sign followed by a constant expression as:
<data_type><variable_name> = value;
Some examples are:
int d =3, f =5;/* initializing d and f. */byte z =22;/* initializes z. */double pi =3.14159;/* declares an approximation of pi. */char x ='x';/* the variable x has the value 'x'. */
It is a good programming practice to initialize variables properly otherwise, sometime program would produce unexpected result.
Try following example which makes use of various types of variables:
namespaceVariableDeclaration{classProgram{staticvoidMain(string[] args){short a;int b ;double c;/* actual initialization */ a =10; b =20; c = a + b;Console.WriteLine("a = {0}, b = {1}, c = {2}", a, b, c);Console.ReadLine();}}}
When the above code is compiled and executed, it produces following result:
a = 10, b = 20, c = 30
Accepting Values from User
The Console class in the System namespace provides a function ReadLine() for accepting input from the user and store it into a variable.
For example,
int num; num =Convert.ToInt32(Console.ReadLIne());
The function Convert.ToInt32() converts the data entered by the user to int data type, because Console.ReadLine() accepts the data in string format.
Lvalues and Rvalues in C#:
There are two kinds of expressions in C#:
- lvalue : An expression that is an lvalue may appear as either the left-hand or right-hand side of an assignment.
- rvalue : An expression that is an rvalue may appear on the right- but not left-hand side of an assignment.
Variables are lvalues and so may appear on the left-hand side of an assignment. Numeric literals are rvalues and so may not be assigned and can not appear on the left-hand side. Following is a valid statement:
int g =20;
But following is not a valid statement and would generate compile-time error:
10=20;
Constants
Classes and structs can declare constants as members. Constants are values which are known at compile time and do not change. (To create a constant value that is initialized at runtime, use the readonly keyword.) Constants are declared as a field, using the const keyword before the type of the field. Constants must be initialized as they are declared. For example:
class Calendar1 { public const int months = 12; }
In this example, the constant months
will always be 12, and cannot be changed — even by the class itself. Constants must be of an integral type (sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, or string), an enumeration, or a reference to null.
Multiple constants of the same type can be declared at the same time, for example:
class Calendar2 { const int months = 12, weeks = 52, days = 365; }
The expression used to initialize a constant can refer to another constant so long as it does not create a circular reference. For example:
class Calendar3 { const int months = 12; const int weeks = 52; const int days = 365; const double daysPerWeek = days / weeks; const double daysPerMonth = days / months; }
Constants can be marked as public, private, protected, internal, or protected internal. These access modifiers define how users of the class can access the constant.
Constants are accessed as if they were static fields, although they cannot use the static keyword. Expressions that are not contained within the class defining the constant must use the class name, a period, and the name of the constant to access the constant. For example:
int birthstones = Calendar.months;
Objects
Objects are programming constructs that have data, behavior, and identity. Object data is contained in the fields, properties, and events of the object, and object behaviors are defined by the methods and interfaces of the object.
Objects have identity — two objects with the same set of data are not necessarily the same object.
Objects in C# are defined through classes and structs — these form the single blueprint from which all objects of that type operate.
Objects have the following properties:
Everything you use in C# is an object, including Windows Forms and controls.
Objects are instantiated; that is, they are created from templates defined by classes and structs.
Objects use Properties (C# Programming Guide) to obtain and change the information they contain.
Objects often have methods and events that allow them to perform actions.
Visual Studio provides tools for manipulating objects: the Properties Window allows you to change the attributes of objects such as Windows Forms. The Object Browser allows you to examine the contents of an object.
All C# objects inherit from the Object.
A class or struct definition is like a blueprint that specifies what the type can do. An object is basically a block of memory that has been allocated and configured according to the blueprint. A program may create many objects of the same class. Objects are also called instances, and they can be stored in either a named variable or in an array or collection. Client code is the code that uses these variables to call the methods and access the public properties of the object. In an object-oriented language such as C#, a typical program consists of multiple objects interacting dynamically.
Struct Instances vs. Class Instances
Because classes are reference types, a variable of a class object holds a reference to the address of the object on the managed heap. If a second object of the same type is assigned to the first object, then both variables refer to the object at that address.
Instances of classes are created by using the new operator. In the following example, Person is the type and person1 and person 2 are instances, or objects, of that type.
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
//Other properties, methods, events…
}
class Program
{
static void Main()
{
Person person1 = new Person(“Leopold”, 6);
Console.WriteLine(“person1 Name = {0} Age = {1}”, person1.Name, person1.Age);
// Declare new person, assign person1 to it.
Person person2 = person1;
//Change the name of person2, and person1 also changes.
person2.Name = “Molly”;
person2.Age = 16;
Console.WriteLine(“person2 Name = {0} Age = {1}”, person2.Name, person2.Age);
Console.WriteLine(“person1 Name = {0} Age = {1}”, person1.Name, person1.Age);
// Keep the console open in debug mode.
Console.WriteLine(“Press any key to exit.”);
Console.ReadKey();
}
}
/*
Output:
person1 Name = Leopold Age = 6
person2 Name = Molly Age = 16
person1 Name = Molly Age = 16
*/
Because structs are value types, a variable of a struct object holds a copy of the entire object. Instances of structs can also be created by using the new operator, but this is not required, as shown in the following example:
public struct Person
{
public string Name;
public int Age;
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
public class Application
{
static void Main()
{
// Create struct instance and initialize by using “new”.
// Memory is allocated on thread stack.
Person p1 = new Person(“Alex”, 9);
Console.WriteLine(“p1 Name = {0} Age = {1}”, p1.Name, p1.Age);
// Create new struct object. Note that struct can be initialized
// without using “new”.
Person p2 = p1;
// Assign values to p2 members.
p2.Name = “Spencer”;
p2.Age = 7;
Console.WriteLine(“p2 Name = {0} Age = {1}”, p2.Name, p2.Age);
// p1 values remain unchanged because p2 is copy.
Console.WriteLine(“p1 Name = {0} Age = {1}”, p1.Name, p1.Age);
// Keep the console open in debug mode.
Console.WriteLine(“Press any key to exit.”);
Console.ReadKey();
}
}
/*
Output:
p1 Name = Alex Age = 9
p2 Name = Spencer Age = 7
p1 Name = Alex Age = 9
*/
The memory for both p1 and p2 is allocated on the thread stack. That memory is reclaimed along with the type or method in which it is declared. This is one reason why structs are copied on assignment. By contrast, the memory that is allocated for a class instance is automatically reclaimed (garbage collected) by the common language runtime when all references to the object have gone out of scope. It is not possible to deterministically destroy a class object like you can in C++.
Note Note
The allocation and deallocation of memory on the managed heap is highly optimized in the common language runtime. In most cases there is no significant difference in the performance cost of allocating a class instance on the heap versus allocating a struct instance on the stack.
Object Identity vs. Value Equality
When you compare two objects for equality, you must first distinguish whether you want to know whether the two variables represent the same object in memory, or whether the values of one or more of their fields are equivalent. If you are intending to compare values, you must consider whether the objects are instances of value types (structs) or reference types (classes, delegates, arrays).
To determine whether two class instances refer to the same location in memory (which means that they have the same identity), use the static Equals method. (System.Object is the implicit base class for all value types and reference types, including user-defined structs and classes.)
To determine whether the instance fields in two struct instances have the same values, use the ValueType.Equals method. Because all structs implicitly inherit from System.ValueType, you call the method directly on your object as shown in the following example:
// Person is defined in the previous example.
//public struct Person
//{
// public string Name;
// public int Age;
// public Person(string name, int age)
// {
// Name = name;
// Age = age;
// }
//}
Person p1 = new Person(“Wallace”, 75);
Person p2;
p2.Name = “Wallace”;
p2.Age = 75;
if (p2.Equals(p1))
Console.WriteLine(“p2 and p1 have the same values.”);
// Output: p2 and p1 have the same values.
The System.ValueType implementation of Equals uses reflection because it must be able to determine what the fields are in any struct. When creating your own structs, override the Equals method to provide an efficient equality algorithm that is specific to your type.
To determine whether the values of the fields in two class instances are equal, you might be able to use the Equals method or the == operator. However, only use them if the class has overridden or overloaded them to provide a custom definition of what “equality” means for objects of that type. The class might also implement the IEquatable<T> interface or the IEqualityComparer<T> interface. Both interfaces provide methods that can be used to test value equality. When designing your own classes that override Equals, make sure to follow the guidelines stated in How to: Define Value Equality for a Type (C# Programming Guide) and Object.Equals(Object).
Apply for C Sharp Certification Now!!
https://www.vskills.in/certification/Certified-C-sharp-Professional