C# - 3 in 1 - Beginner - S Guide+ Simple and Effective Tips and Tricks+ Advanced Guide To Learn C
C# - 3 in 1 - Beginner - S Guide+ Simple and Effective Tips and Tricks+ Advanced Guide To Learn C
This document is geared towards providing exact and reliable information in regards to the topic and issue covered. The
publication is sold with the idea that the publisher is not required to render accounting, officially permitted or otherwise qualified
services. If advice is necessary, legal or professional, a practiced individual in the profession should be ordered.
From a Declaration of Principles which was accepted and approved equally by a Committee of the American Bar Association and
a Committee of Publishers and Associations.
In no way is it legal to reproduce, duplicate, or transmit any part of this document in either electronic means or printed format.
Recording of this publication is strictly prohibited, and any storage of this document is not allowed unless with written
permission from the publisher. All rights reserved.
The information provided herein is Provinced to be truthful and consistent, in that any liability, in terms of inattention or
otherwise, by any usage or abuse of any policies, processes, or directions contained within is the solitary and utter responsibility
of the recipient reader. Under no circumstances will any legal responsibility or blame be held against the publisher for any
reparation, damages, or monetary loss due to the information herein, either directly or indirectly.
Respective authors own all copyrights not held by the publisher.
The information herein is offered for informational purposes solely and is universal as so. The presentation of the information is
without a contract or any type of guarantee assurance.
The trademarks that are used are without any consent, and the publication of the trademark is without permission or backing by
the trademark owner. All trademarks and brands within this book are for clarifying purposes only and are owned by the owners
themselves, not affiliated with this document.
Table of Contents
C#
A Comprehensive Beginner's Guide
to Learn About the Realms of C# From A-Z
Introduction
Chapter 1 : Getting Started With C#.NET
CLR
Assembly
CIL
Chapter 2 : The Basic Elements of a Program
Chapter 3 : The Program Makes Decisions
Chapter 4 : Creating Loops
Loops That Start at Zero
Problems With the For Loop
Initialization of Variables in Loops
Problems With Variables in the Loops
Verify Changes in a Program
Guarantee the Execution of the While Loop
Nested Loops
Chapter 5 : The Functions and Methods
The Name of the Function
Problems in Declaring Functions
Name in Invocation
Be Careful With the Type of Return
Return’s Position in the Function
Parameter Order
Types of Parameters
To Know the Functions
Conclusion
Resources
C#
Simple and Effective Tips and Tricks
to Learn C# Programming Effectively
Introduction
Chapter One : What Is C#?
Community
Professional Version
Enterprise Version
Chapter Two : Getting Started With C#
Array Length
Array Loop
Item Removal
List Creation
Concatenation
Chapter Three : C# Conditionals
Chapter Four : Interactive Programming
Chapter Five : C# Loops
Chapter Six : C# Methods
Chapter Seven : Object-Oriented Programming
Chapter Eight : C# Classes Explained Further
Chapter Nine : Writing Secure Code
Spoofing
Tampering
Repudiation
Information Disclosure
Denial of Service
Privilege
Conclusion
References
C#
Advanced Guide to Learn C# Programming Effectively
Introduction
Chapter One : Getting Familiar with the Foundations of C#
Defining Classes
Using a Class in a Console Application
Printing a Statement in a Console Application
Performing a ‘Read’ on the Command Prompt
Using Fields and Properties
Defining a Field
Defining Properties
Read-Only Properties
Write-Only Properties
Indexed Properties
Using an Instance of a Class
Defining an Interface
Implementing an Interface
Inheritance
Encapsulation and Aggregation
Polymorphism
Access, Class, and Member Modifiers
Chapter Two : Working with the Assembly Viewer and UserControls
The ‘using’ Statement
Working with the Assembly Using Reflection
The ‘Broadcaster’ Class
Using the ‘Broadcaster’ Class
Defining the Interface for the ‘Broadcaster’ Class
Implementing the ‘StatusBar’ Form Control
Implementing the ‘MainMenu’ Form Control
Implementing the ‘OpenFileDialog’ Form Control
Making the Graphical Interface of the UserControl
Promoting Events in Constituent Controls
Other Choice for Member Promotion
Chapter Three : Working with Video Kiosk Using C#
GDI+ Namespaces
PlayControl
Background
Buttons and Custom Controls
Conditional Logic and using Arrays
Using Graphics Objects
Paint Event Handler
Overloading OnPaint
Invalidating a Control
Pens
Defining Tracker Control
SetStyle
ControlPaint
Drawing a 3D Border
Drawing a Button Control
Graphics.DrawImage
Using TimeSpan to Tell Time
Formatting Strings
Adding Controls to a Toolbox
Catching and Handling Exceptions
Making a TODO List
The Process Class
Chapter Four : Personalizing the Visual Studio .NET Framework Environment
Using IDTWizard
Pass-By Referencing
Testing the Wizard
Creating a New Template from a Pre-Existing Template
Adding Files to the Wizard Library Template
Modifying default.js
Modifying common.js
The Wizard Launch File
Creating a VSDir File
The Common Environment Model
Writing Code, using Macros
User Interface Strategies:
Dialog Form Strategies
Implementing the Wizard
Registering Wizards
Testing the Wizard using a Macro
Running the Wizard from the Command Window
Returning to JScript
Using the regasm Utility
Conclusion
References
C#
A Comprehensive Beginner's Guide
to Learn About the Realms of
C# From A-Z
BENJAMIN SMITH
Introduction
The ease with which you have access to a computer today has led people to use them in many
activities, using software that performs specific tasks. When the computer is required to carry out
other types of actions, and the available programs do not, it is necessary to tell it in its language
how it should act, and for this, the programming languages are used.
Programming languages try to resemble our own way of expressing ourselves. For this, they
have their own syntax and semantics, as well as symbols that allow us to tell the computer what
processes and what data to handle, how to store them, what actions to perform with them and
how to present them to the user. For this reason, it is important to have a methodology that
allows learning correct and effective habits to solve problems, which, when subdivided for better
understanding, will facilitate their resolution.
Once the problem has been understood, a sequence of steps to be carried out is constructed,
better known as an algorithm, which will allow testing whether the logic is correct and whether
the results that will be obtained will be adequate. The potential of the current programming
languages is enormous because it allows for the automation of very different types of activities.
As such, this reduces the time that is invested in doing it manually and, if you learn to use them
correctly, it will be easier for the users who use such programs.
Learning to program is a task that requires practice and patience, but it is also a fascinating
activity. If you also have an excellent book and the necessary consistency, the results will be
excellent. Congratulations on this new challenge that is about to begin!
C # or C Sharp is a programming language that is included in the .NET Platform and runs in the
Common Language Runtime (CLR). The first language of importance to the CLR is C #, much
of what the .NET Platform supports is written in C #.
C # is derived from C and C ++, and it is modern, simple, and entirely object-oriented. It
simplifies and modernizes C ++ in the areas of classes, namespaces, method overloading, and
exception handling. C ++ complexity has been removed to make it easier to use and less error-
prone.
Many books, when going through the chapters, mention all the details of the language, along
with its basic principles. This ends up creating a lot of confusion, especially because the student
cannot differentiate exactly what is essential to learn in the beginning, from what can be left to
study later.
Whether or not an abstract class should have at least one abstract method, if it only accepts
Boolean arguments and all the details about inner classes, it really shouldn't be a concern for one
whose primary goal is to learn C #. This type of information will be acquired over time and is not
necessary at the beginning.
In this course, we separate this information into special boxes, as they are extra information. Or,
we just quote in some exercise and leave it to the reader to look for additional information, if it is
of interest.
Finally, there is still something to mention about the practice, which must be taken seriously:
practice is very important. We recommend students to study each section of the book and
practice a lot of code and variations.
Chapter 1
Getting Started With C#.NET
This book is intended for all those who want to learn the C # programming language and have
basic programming knowledge or have no previous experience programming computers. The
focus of the book is to guide the learning of C # (an object-oriented) language step by step. In the
first chapters, we will take a structured philosophy to make learning even easier for all of us.
Discover .NET
The .NET Framework is a solution to all the problems involved in the development of
applications, providing great benefits not only to the developer but also to the development
process. First of all, .NET allows us to work with existing code; we can use COM components,
and even, in the situation where we need to use the Windows API. When the .NET program is
ready, it is much easier to install on the client's computer than traditional applications since it has
a strong integration between languages.
A C# programmer can easily understand the code of a Visual Basic .NET programmer, and both
can program in the language they are most comfortable with. This is because all the languages
that make use of .NET share the .NET libraries, so it does not matter in which language we
program in, we can recognize it in any language. Next, we will know the different components of
.NET: Common Language Runtime (CLR), Assembly, and Common Intermediate Language
(CIL).
CLR
The first component of .NET that we will know is the Common Language Runtime, also called
CLR. This is an execution program common to all languages. This program is in charge of
reading the code generated by the compiler and starts its execution. It does not matter if the
program was created with C#, Visual Basic .NET, or some other .NET language, the CLR reads
it and executes it.
Assembly
When we have a program written in a .NET language, and we compile it, the assembly is
generated. The assembly contains CIL in the compiled program and also the information about
all the types that are used in the program.
CIL
The .NET programs are not compiled directly into compiler assembly code; instead, they are
compiled into an intermediate language known as CIL. This language is read and executed by the
runtime. The use of CIL and runtime is what gives .NET its great flexibility and its ability to be
multiplatform.
The Framework of .NET has Common Language Specifications or CLS. These specifications are
the guidelines that any language that you want to use .NET must meet to be able to work with the
runtime. One advantage of this is that if our code complies with the CLS, we can have
interoperability with other languages, for example, it is possible to create a library in C #, and a
Visual Basic .NET programmer can use it without any problem.
One of the most important points of these guidelines is the CTS or Common Type System. In
programming languages, when we want to save information, it is placed in a variable, the
variable will have a type depending on the information to save, for example, the type can be to
save an integer, the other to store a number with decimals and the other to save a phrase or word.
The problem with this is that each language store information differently. Some languages store
integers with 16-bit memory and other with 32-bit; even some languages, such as C and C++, do
not have a type for storing strings or phrases.
To solve this, the .NET Framework defines through CTS how the types will work in their
environment. Any language that works with .NET must use the types as outlined in the CTS.
Now that we know the basic concepts, and we can see how all this comes together.
At the bottom, we find another window; in this area, there are usually the sections that the
compiler will use to communicate with us. For example, we will see the window that indicates
the errors that our program has; at the top of the window, we will see the menus and the toolbars.
If, for any reason, we close the source code editor or it does not appear in our user interface, the
easiest way to find it is through the Solution Explorer. Simply go to the document that represents
your source code and double click on it, the window with the source code editor will appear.
The Solution Explorer shows us the information about the solution in a logical way if we
observe, it is like a small tree. At the root, we find the solution; each project we have in that
solution will be a branch, each project, in turn, will also have its divisions. In our case, we see
three elements; two of those elements are folders; in one, we keep the properties of the project,
and in the other, the references (during this book, we will not use these folders). The fourth
element is a document called Program.cs, this represents the document where we save the source
code of our application. We see that the extension of the C# programs is .CS.
In the editing area, we can see that we have a skeleton so that, from there, we can create our own
program. To understand what we have, there is necessary to know a concept: namespace. The
namespace is a logical grouping; for example, all the code that we can have related to
mathematics can be grouped inside the namespace of Math. Another use that namespace has is to
solve conflicts with names, for example, let's suppose that we have a massive project and several
programmers working on it. Two or more programmers could have created a method that had the
same name; this generates a conflict since the program could not know which version to use. The
way to solve this is that each programmer has its own namespace and refers to the corresponding
namespace according to the version we want to use.
The .NET Framework provides us with various namespaces where we have thousands of classes
and methods already created for our use. When we want to use the resources found in a
namespace programmed by other programmers or by us, we must make use of a C # command
known as using.
As we can see at the top of the code, we have several using references to the namespaces that our
application needs; if we needed to add more namespaces, we would do it in this section.
Below is defining the proper namespace of our project; this is done as follows:
namespace MyProject
{
}
The namespace we are creating is called MyProject. As we can see, the namespace uses {} as
delimiters; this is known as a code block, and everything that is placed between {} will belong to
the namespace. This is where it will be necessary to write the code corresponding to our
application.
Inside the code block, we find the declaration of a class, C# is an object-oriented language, and
that is why it needs us to declare a class for our application. The class has its own block of code,
and in our application, it will be called Program. The concept of the class will be covered in
Chapter 10 of this book.
All programs need a starting point, a place that indicates where the program execution starts, in
C#, as in other languages, the starting point is the Main() function; this function also has its own
code block. Within this function, we will generally place the main code of our application,
although it is possible to have more functions or methods and classes. The parts and
characteristics of the functions are seen in Chapter 5 of this book.
Now it is time to create our first application. We are going to modify the function code, as shown
below. When we are adding the statement inside Main(), we must notice that it happens
immediately after the point is placed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main (string [] args)
{
Console.WriteLine ("Hello World!");
}
}
}
If we can manage to observe during writing the code when you will write the word Console and
then insert the dot, a box will appear listing different elements. This box is called autocomplete
and allows us to work quickly and reduce the number of syntax errors. The autocomplete box
shows us a suggestion of the word, command, variable, etc. that could be used next. If we want,
we can select it from that list, and it will write for us; as we progress and become familiar with
C# programming, we will see that this feature is so helpful.
In our example, we have placed a statement that will write the Hello World message on the
console. This is a very simple program, but it will allow us to learn how to compile the
application and see the program running.
As we already know, the window that appears at the bottom of our user interface is used by the
compiler to communicate; we see that a window appears that gives us a list of errors. In the next
book, we will learn how to use it; for now, we simply need to know that it is always necessary to
solve the first problem in the list and that we can go directly to the error by double-clicking on it.
The class view window is divided into two sections; the upper section shows the logical and
hierarchical relationship of the elements while the lower section shows the methods that make up
a particular class.
At the root of the tree, we find the project; it will contain the necessary references and the
namespaces of HelloWorld. If we had more namespaces, they would appear there, when opening
the HelloWorld namespace we find the classes that are unclaimed within it. In this case, we only
have the Program class; if we select it, we will see that at the bottom, the elements that are
declared inside are shown. In our example, we have the Main () method.
If at this time, we double click on any of the methods, we will automatically go to the code
where it is defined. Because our program is very small, we may not see the advantage of this, but
in programs with thousands of lines of code, being able to navigate quickly is a great advantage.
The time has come to learn how to develop computer programs. Some people think that
programming software is complex and difficult; however, this is not true or was a long time ago.
To be programmers, we only need to know a programming language and the necessary
techniques to develop programs. Throughout this chapter, we will learn both.
Sometimes it happens that we forget to put the string in quotation marks or that only the
beginning quotation mark has been placed. It is important not to forget to always put the strings
between the two quotes. If we don't do it this way, the compiler can't find the string correctly or
where it ends, and the statement will give us a compile error.
The error list gives us a description of the error and also allows us to see the line number where
the error is located. An easy way to get to it is to simply double-click on the error description so
that the C# environment will take you directly to where the error is. Let's put the semicolon back
where it was in the beginning and compile. This time, the program can be compiled and executed
without problems, based on the correction that we have made in advance. The error has been
fixed. The solution provided by C# to correct errors is practical and simple to implement.
Now let's experience another bug. In the first sentence we delete the closing parenthesis and then
compile to see what happens:
Let's correct the error and recompile it. Everything must be okay. But what we will do now is
delete the closing quotation marks from the string in the first statement. This error presents us
with a more interesting scenario, and it is convenient for us to understand what is happening.
Let's compile the program and look at our list of errors. This will be much more extensive than
the previous ones:
Something interesting has happened here, even though we have only created one error: in the list
of errors, there are three errors. This is because one error can cause other errors in the following
code. By not closing the string, the compiler doesn't know where the statement ends and believes
that the closing parenthesis and semicolon are part of the string. That's why it also shows us that
the parenthesis and semicolon are missing.
Since errors can be chained, as in this example, we always need to fix the error that comes first.
If we were to try to fix the semicolon error first, it would not be obvious to see what the error is
in that line, since we would see that the semicolon itself is written.
Sometimes it happens that our program shows many errors, but when we fix the first error, most
of them disappear. This is due to factors similar to those we have just discussed above.
A common mistake that beginners make when naming their variables is that they forget how they
named the variable and write it sometimes in lower case and sometimes in upper case. This leads
to errors in logic or syntax. To avoid this, we can use a table that contains information about the
variables of our program.
When executing it, in effect, we see that after using Write (), the next element that is written is
placed in the same line, but when using WriteLine (), the next element appears in the following
line. This is a clear example of what was explained previously.
The Variables
Computers not only write messages on the screen, but they also have to do useful things. To do
them, they need information. The information must be stored and manipulated in some way.
When we want to store something in everyday life, we can use boxes, so anything we want to
store can be placed in a cardboard box, for example. However, the size of the box will depend on
what we want to store. A pair of shoes can fit into a small box, but we cannot put a television in
that box. If we start storing a lot of things in boxes, we will soon have too many, and it will be
difficult to find what we have stored. So one way to deal with this is through labels, we can label
each box with the content, and in this way, we can quickly find what we are looking for.
The variables in the computer work similarly to our storage boxes. We can imagine them as
small boxes that exist in computer memory, and their size will depend on the information they
are supposed to store. This is known as the variable type. To access that box or variable, we give
it a name that would be the label with which we identify it.
To make use of a variable, the first thing we have to do is declare it. The declaration of this is
something very simple. As a first step, we have to assign the type and then the name. The
variables in C# must be named according to some simple recommendations:
The names of the variables must begin with a letter.
It is possible to place numbers in the variable names, but not to start the name with
them.
The names of the variables cannot bear any signs except for the underscore _ .
Variables cannot have accents in their names.
When we name the variables, we have to take into account that C# is case sensitive, so a variable
called cost is not the same as another variable called COST or another one called Cost.
It is recommended to name the variables with names that refer to the information they will keep.
If we get used to doing this since we started programming, we will avoid many problems in the
future, and it will be much easier to fix our programs when they have errors.
Let's look at an example of how we can declare a variable that stores integer numerical values.
The type that stores these values is known as int.
int cost;
We see that at the end of the sentence, we have placed the semicolon. If we need to declare more
variables, we can do it in the following way:
int cost;
int value;
int tax
But it is also possible to declare the variables on a single line. For this, we simply separate the
names of the variables with commas. Do not forget to put the semicolon at the end of the
sentence.
int cost, value, tax;
It is important to know the types and information that can be saved, as this will allow us to save
the necessary information and use the least amount of memory. We can learn the ranges of the
types or print a table and have them at hand. With practice, we will be able to use the types
without having to check the ranges regularly.
An important point to note is that the assignment is always carried out from right to left. This
means that the value to the right of the equal sign is assigned to the variable to the left of the
equal sign. If we don't do it this way, the value cannot be assigned or will be assigned to the
wrong variable.
Once we have declared the variable, we must initialize it. Initializing a variable is assigning a
value to it for the first time. This allows us to give it an initial value that can be useful in the
execution of our program (not only can we assign a variable a fixed value, but it can also be from
a text entered by the user or from the registration of a database).
To assign a value to a variable, either during initialization or during the course of the program,
we use an assignment operator, the equal sign. Let's see below an example of how to assign
values:
cost = 50;
value = 75;
tax = 10;
In this case, the cost variable stores the value of 50, the value variable stores 75, and the tax
variable stores the value 10.
An invalid assignment would be as follows:
50 = cost;
In this case, nothing is assigned to the cost variable. The variable that receives the value is
always placed to the left of the equal sign.
If we need it, it is possible to initialize the variable when declaring it. This is very comfortable,
and if we do so, we avoid forgetting the initialization of the variable. To do this, we place the
type of the variable followed by the name to be used in the variable, and immediately with the
assignment operator, we place the value.
int cost = 50;
Arithmetic Operations
Being able to save information is very important, but it is much more important that we can
retrieve and manipulate that information to do something useful with it. For this, we must begin
to perform the basic arithmetic operations: addition, subtraction, multiplication, and division,
something very common in any computer system.
When we want or need to perform an arithmetic operation, we must use an operator. Each
operation has its own operator, which is in charge of processing the numbers, performing the
determined calculation, and then returning the desired result.
Operator Description
= Assignment. This operator is already known to us.
+ Sum. We can add the values of the variables or numbers
- Subtraction. To subtract the values of the variables or numbers.
* Multiplication. Multiplies the values of the variables or numbers.
/ Division. Divide the values of the variables or numbers.
% Module. It gives the remainder of the division.
Let's see some examples of how to use these operators. Let's imagine that we have already
declared and initialized the variables. To save the sum of two numbers in the result variable, we
do the following:
result = 5 + 3;
As we have seen, the expression on the right is assigned to the variable, so in this case, the
expression 5 + 3 is evaluated, and its result, which is 8, is stored in the result variable. At the end
of this sentence, the result variable has a value of 8, which can be used within the same function
or in the procedure where it was declared.
Operations can also be performed with variables and numbers. Suppose that variable a has been
declared and assigned a value of 7.
result = a - 3;
Again the expression a-3 is evaluated since the value inside of a is 7. The evaluation gives the
value of 4, which is assigned to the result variable.
If we want, we can only work with variables. Now we will assume that variable b has been
declared and that we have assigned the value 8.
result = a * b;
Then, the expression a * b is evaluated, which gives the value 56, which is assigned to the
variable result at the end of the expression.
If what we want is division, we can do it as follows:
result = a / b;
In this case, divide the value of a by the value of b. The result is 0.875. Since the number has
decimal values, we must use variables of some type that allow us to save them as float or double.
And finally, we have the module.
result = a% b;
In this case, we receive as a result the value of the remainder of dividing a by b.
Let's see a small program where what is learned in this section is shown.
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Start the application here
static void Main(string[] args)
{
// We declare the variables, now of floating type
float a, b, result;
// We initialize the variables
a = 7;
b = 8;
result = 0 ;
// sums
Console.WriteLine("Sums");
result = 3 + 5;
Console.WriteLine("Result = {0}", result);
result = a + 3;
Console.WriteLine("Result = {0}", result);
result = a + b;
Console.WriteLine("Result = {0}", result);
// Subtract
Console.WriteLine("Subtract");
result = a - b;
Console.WriteLine("Result = {0}", result);
result = b - 5;
Console.WriteLine("Result = {0}", result);
result = b - a; // Variable b is subtracted from
Console.WriteLine("Result = {0}", result);
// Multiplications
Console.WriteLine("Multiplications");
result = a * 5;
Console.WriteLine("Result = {0}", result);
result = a * 3.5f;
Console.WriteLine("Result = {0}", result);
result = a * b;
Console.WriteLine("Result = {0}", result);
// Divisions
Console.WriteLine("Divisions");
result = a / 3;
Console.WriteLine("Result = {0}", result);
result = a / b;
Console.WriteLine("Result = {0}", result);
result = b / 2.5f;
Console.WriteLine("Result = {0}", result);
// module
Console.WriteLine("Module") ;
result = a % b;
Console.WriteLine("Result = {0}", result);
}
}
}
We can see the execution in the following figure:
The most common errors in mathematical expressions are forgetting the semicolon, making the
wrong assignment, misspelling the variable name, and incorrectly grouping operations. Using
parentheses for grouping helps a lot to reduce errors.
Precedence of Operators
So far, we have used simple arithmetic expressions, but in real life, more complicated
expressions may be needed. So, if these expressions are not placed properly, this can lead to
problems.
For example, let us look at the following expression.
result = 3 * 5 + 2;
This expression presents a problem for us at this time. We don't know if you first do 3*5 and add
2, which results in 17, or if you add 5+2 and then multiply it by 3, which results in 21.
The way to find out is through operator precedence. This tells us the order in which the
operations are carried out. This order depends on the type of operator used. Some operators have
more precedence than others, i.e., they are executed first.
The following table shows the precedence of the operators we have seen so far in C#. They are
listed from highest to lowest precedence.
Operator Description
* Multiplication
/ Division
% Module
+ Addition
- Subtraction
This means that when we have an arithmetic expression like the one in the example, first, the
multiplication would be carried out and then the addition, so with this, we can deduce how C#
would evaluate the expression.
But sometimes it would be better if we could organize our expression to make it easier to read
for us or to indicate precisely how to do the operation. For us to organize an expression, we make
use of parentheses. Each section we have in the parentheses is evaluated as an expression, and
the result is passed to the rest of the expression. Suppose we have the following expression:
result = (3*5) + 2;
We see that using the parentheses a part of the expression has been grouped, so it is evaluated
and equivalent to:
result = 15 + 2;
This, in the end, evaluates in:
result = 17;
Let's see another example of how we can use the parentheses to indicate how we should evaluate
the expression.
result = 3 * (5+2);
The first thing that happens is that the expression in the parenthesis is evaluated.
result = 3 * 7;
That gives us the value:
result = 21;
Let's look at a slightly more complicated example.
result = (3+7) * (36 + 4 *(2+5));
Let's see what happens:
result = 10 * (36 + 4 * 7);
Then we continue to evaluate:
result = 10 * (36 + 28);
This gives as a result:
result = 10 * 64;
And in the end, we get:
result = 640;
Fortunately, C# does all these evaluations and all these calculations for us, but now we know
how it happens, and we know that we can use the parenthesis to organize our arithmetic
expressions.
Conversion of Variables
The ReadLine() method presents us with a limitation at this time since it only returns the value as
a string. But we cannot use a string in arithmetic operations or assign it directly to a numerical
variable.
What we have to do is convert that numerical data stored as a string to a numerical value useful
for our purposes. C# provides us with a class that allows us to make conversions between
different types of variables. This class is known as convert and has a large number of methods
for conversion. Here we will only look at how to convert to integers and floats, as these are the
types we will be working with through this book primarily. However, the other methods are used
similarly, and we can find the necessary information about them in MSDN (Microsoft Developer
Network).
If we want to convert from the string type to the int type, we will use the ToInt32() method. This
needs a parameter, which is the string we want to convert. The method returns an int type value,
so it is necessary to have a variable that receives it.
An example of this is:
a = Convert.ToInt32(input);
Similarly, we can convert the string to a float type variable. In this case, we will use the
ToSingle() method. This also needs a parameter, which is the string that contains the value to
convert. Since a float value returns, then we must have a float type variable that receives it.
value = Convert.ToSingle(input);
Since we have the values converted to numbers, then we can make use of them. Let's see an
example where we ask the user for information.
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Start the application here
static void Main(string[] args)
{
// We declare variables
string input = "";
int a = 0, b = 0, result = 0;
// We read a string
Console.WriteLine("Enter your name");
input = Console.ReadLine();
int Entry = 0;
Console.WriteLine("Hello {0}, how are you?", Entry);
// We read two values and add them together.
Console.Write("Give me an integer:");
input = Console.ReadLine();
// Convert the string to integer
a = Convert.ToInt32(input);
Console.Write("Give me another integer:");
input = Console.ReadLine();
// Convert the string to integer
b = Convert.ToInt32(input);
// Add the values
result = a + b;
// We show the result
Console.WriteLine("The result is {0}", result);
}
}
}
Now let's compile and run the application. To enter the data, simply type it with the keyboard
and when finished press the ENTER or RETURN key.
It is also possible to convert from numbers to strings. For this the ToString () method is used,
which is available in all numeric C # types. In this way we can use the information of the
numerical variables in functions or methods that work with strings. The method does not change
the type, it just returns a string containing the text of that value.
Elements of a Flowchart
It is time to learn the basic components of a flowchart. With these diagrams, we can represent the
algorithm, and they are easy to make and understand. Another advantage they have is that they
are language independent, which gives us the flexibility to solve the problem and use our
solution in any language.
The flowchart is a graphical representation of the algorithm and has different components. Each
component is a figure, and it represents a type of activity. Inside the figure, we place a
description of the step that is happening there, using arrows we indicate which is the next step,
and it gives us the idea of the general flow of the algorithm. Sometimes, we add extra
information to the arrows, but we will see this later. Although at this moment we will not use all
the components of the flowchart, we will know the most important ones, since in the following
chapters we will use them.
The first component is oval-shaped and is known as the terminator. This is used to indicate the
beginning or the end of the algorithm. When we see it, we can immediately know where the
algorithm starts, and we can continue from there. Remember that algorithms must have an end to
be valid. If the terminator is started, we put the message inside Start, and if the terminator
indicates where the algorithm ends, then the message: End.
The next element is known as a process. This has the shape of a rectangle and serves to indicate
that a process must take place there precisely. The description of the process is indicated inside.
Similar to the process, we have a pre-defined process. Its shape is also a rectangle, but it has two
lines on the sides. It is used to indicate that we will make use of a process that has already been
defined elsewhere.
An example of this would be a method, like the ones we have already used. We'll mainly use it to
indicate calls to functions or methods defined by ourselves.
Our next element is known as a condition. We will use this element when we learn how to make
the program to make its own decisions. Basically, it serves to make a selection among the
possible paths of execution of the algorithm, which will depend on the value of the evaluated
expression. Its shape is like a rhombus, and from the corners of this one, the arrows will appear
towards the possible paths of execution of the algorithm.
Then we find a component known as data. Its shape is that of a parallelogram, and we can use it
to indicate the output or input of the data.
An example of this would be when we carry out a request for a value to the user or when we
display a value on the screen. Inside it, we indicate what data is requested or presented.
We have seen the main elements of the flow chart. Now we can do an exercise that shows the
solution of a problem on the computer.
Since we know the problem and have subdivided it into several sub-problems, we can more
clearly identify the data we need to work on it. The description of the problem provides us with
two explicit pieces of information: the area and the perimeter. But we also immediately
recognize two implicit data that are necessary: the height and the width of the rectangle.
We know that we need a string to receive the value written by the user, but as such, this string is
not part of the problem. However, it helps us to solve it so that the string will be working data.
The data we have identified will be placed in a table as follows:
We have decided to use the float type since we can have decimal values in the perimeter
calculation. Since a rectangle with a width or height of 0 does not make sense, we have selected
1 as the initial value for these variables.
Now the most important step comes: creating the algorithm. However, if we observe the way we
subdivide the problem, we can see that it gives us an indication of the steps that need to be put in
the algorithm.
With this information, we created the algorithm with the flowchart. In it, the sequence of steps
appears in the correct order. Let's see how the diagram looks.
We can observe how we have used the trapezoid when it is necessary to ask or show data to the
user. The calculations with the corresponding formula are in the rectangles since they are various
processes, and the terminators represent the beginning and end of the algorithm.
In the programs created so far, we have seen that the algorithms had only one sense of resolution.
In this chapter, we will learn other ways to have our programs make decisions based on the
analysis of different parameters. We will also learn how to create algorithms with varying paths
of execution to be able to solve problems based on previous analysis.
Decision Making
Not all problems are solved linearly, sometimes it is necessary to have to make a decision or
execute certain actions when a condition is met, and others when it does not. Let us suppose that
our problem is to maintain the temperature of a bucket of warm water. To do this, we can add hot
or cold water. In this problem, we would need to decide what kind of water to add.
Similarly, there are many problems that we need to know a condition or make a decision on how
to solve them. In C#, it is easy to achieve this since the language provides us with different tools
to cope with it. We will have to use expressions, and these will be evaluated. In this case, we will
use relational expressions and logical expressions, which will be evaluated, and depending on the
result of that evaluation, certain steps of the algorithm or others will be carried out. Let's start by
knowing the expressions we need.
Relational Expressions
Relational expressions are used to express the relationship between two values. Values can be
contained within variables or explicitly placed. These expressions, like arithmetic expressions,
have their own operators. The expression will be evaluated, but the result of the evaluation will
have only two possible values: true or false.
Both types of values bool and true are used to indicate that the evaluated expression is true. The
value of false for its part is used to indicate that the evaluated expression is false.
Let's start by getting to know the relational operators first. Then we will look at examples of
relational expressions with their resolution.
Relational Operators
In the table below, we can see the relational operators in C#. The way their signs are written is
the way we must place them in our program.
Sign Operator
== Equality
!= Not the same
> Greater than
< Smaller than
>= Higher than the same
<= Less than equal
The equality operator is represented by two equal signs together without space. Placing a single
equal sign indicates that the operator will be for assignment. This can lead to logic errors because
an assignment always evaluates to true, but equality does not. This operator is the simplest.
Suppose we already have the variables and initialize them with the following values:
int a = 5;
int b = 7;
int c = 5;
int d = 4;
Now we will create our first expression and evaluate it:
a == c
As the value contained in a is 5, and the value contained in c is also 5, we see that 5 is equal to 5,
so the expression is evaluated as true. Let's see what happens in the next expression:
a == d
In this case, the value contained in d is 4, so the expression 5 equal to 4 is not fulfilled, and the
value of the expression is false. On the right side and the left side of the expression, we can place
any value, variable, or expression. If we were to place an expression, first, it would be evaluated.
Then we would proceed to evaluate the main relational expression.
a == (3 + 2)
In this case, 3 + 2 is evaluated as 5, and then 5 equals 5, which gives us the final value of the true
expression. Another example is the following:
(b - 2) == d
When evaluating b - 2, we get 5, and then the expression is 5 equal to 4, which obviously gives
us a false final result.
This is how relational expressions are evaluated, and now we'll see more examples with other
operators. We also have the inequality operator, which is created employing an exclamation
mark and then the equal sign.
a != 7
In this case, we have 5 that is not equal to 7, which is true, and we get the true value as a result of
the evaluation.
a != c
For this expression, we have 5 that is not equal to 5, and the expression is evaluated as false,
which gives us false as a final value. The > operator is used to evaluate a relationship of the type
greater than. If the value on the left side is greater than the value on the right side, it will return
true; otherwise, it will return false.
b>a
This is 7 greater than 5 and results in true.
a>b
In this case, 5 greater than 7 is false, and the result of the expression is false.
b>b
This expression gives us 6 greater than 6, which, if we analyze all the steps up to here, indicates
that it is false as well, and we get false as a result.
In the < operator, we evaluate a relationship of the type less than. It gives true as a result when
the value on the left side is less than the value found on the right side. If this is not true, then the
value returned will be false.
d<a
We have 4 less than 5, which is true, and the result is true.
d < (a - 3)
The expression to be evaluated is 4 less than 2, and it is had false as a result of the expression.
d<d
This expression also results in falsification, since 4 less than 4 is not true. To evaluate whether a
value is greater than or equal to another value, we use the >= operator. The way it works is
similar to the other operators.
b >= a
For this expression, we have 7 greater than equal to 5, it is true, and it gives true value.
b >= (a + c)
In this case, we would get 7 greater than equal to 10, which we know is false and, therefore, as a
result, and we would get false.
b >= b
Here we compare the difference in result in relation to using >= instead of >. For this expression,
we evaluate 7 greater than equal to 7. This is true, and the final result is true. Similarly, we have
the <= operator, but it evaluates in reverse.
a <= b
The expression to be evaluated is 5 less than equal to 7, and we get true as a result.
(a + c) <= b
In this case, we have 10 less than equal to 7, and it is false.
(a + 2)<= b
In this last expression, 7 less than equal to 7 is true, and again, we get true as a result.
A very common mistake that happens when you start programming in C # is to confuse the
equality operator with the assignment operator. If you get an error in an expression, you need to
check this. Let's not forget that the assignment has an equal sign, and equality equals a double
sign.
Operators that are written with two signs must be written correctly. It is not the same> = that =>.
This can lead to syntax errors, but precisely writing them will make them correct. We must also
remember that they are written without spaces between the signs since this leads us to another
syntax error.
Using if
We have already learned how to use relational expressions and the return type. It is time to do
something practical with them. This type of expression is used in different cases but generally in
selective or repetitive structures.
The selective structures will be studied in this chapter, the repetitive ones in a later chapter.
Selective structures are those that allow us to make a selection between two or more possible
execution routes. The selection will be made based on the value of an expression. This
expression can be a relational expression. Our first selective structure is known as if, which is
conditional If. If such a thing happens, then do such a thing. The use of the If is simple:
if (expression)
Statement to execute
The use of If requires that we have to put an expression for evaluation in the parentheses. If the
result of this expression is true, then the statement to execute is carried out.
If the evaluation result is false, then the statement to be executed is never carried out, or in other
words, it is ignored.
In the flowchart, the If is represented by a rhombus. Inside the rhombus, we place the expression
to evaluate, from the corners, we get an execution path if the condition is met or in the case that
it is not met.
Let's see the first example where we can use if and the expressions. We will create a program
that asks the user for a number, and the computer must say if the number is positive or negative.
To see the algorithm of this program, we create its flow chart and include the necessary if's.
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
public static string Value { get; private set; }
// This is the main function of the program
// Start the application here
static void Main(string[] args)
{
int number = 0; // Where we keep the number
string value = ""; // To save the string given by the user
// We ask for the number
Console.Write("Give me an integer:");
Value = Console.ReadLine();
number = Convert.ToInt32(value); // Convert the string to integer
// We use if with the expression for the
case of positives
if (number >= 0)
Console.WriteLine("The number {0} is positive", number); // is
executed if number> = 0 is met
// We use if
with the expression for the case of negatives
if (number < 0)
Console.WriteLine("The number {0} is negative", number); // run if
number <0 is met
}
}
}
The first part of the program is very easy to understand. After this one, we came across the first
if-sentence. For this, if you have the expression number >= 0. If that expression is evaluated as
true, then the next statement is executed; otherwise, it will be ignored, and the program will
continue.
Suppose that the value stored in number is 3, and then the relational expression returns a value of
true. When true is obtained, the If leads to execution and the message that a positive number is
executed.
Then we continue with the next If. For this one, the expression is number < 0, as in this example
number is worth 3, then the expression is evaluated as false, so, while the value of the expression
is false, If will not execute at any time the message that says that the number is negative. This is
exactly what we want this program to do from the beginning.
This is the result of the execution when we pass a positive number for the program.
In this case, we give a negative number, and we can observe the behavior of the program.
When we use if, we should never put a semicolon after the parentheses since doing so is not a
syntax error but a logic error. The compiler interprets this as if we want an empty statement to be
executed when If is true. We see that the If statement always holds regardless of how the
expression is evaluated, we may have this error.
This is a good time to start experimenting in our developments, changing the values, both
negative and positive, including zero and see how our program will respond.
As we saw, the If can be very useful for the program to make the correct decision; however, it
has only been able to execute a statement. We will often encounter the case when we need more
than one statement to be executed if the condition is met. A good option to solve this problem
found is to put a code block to If. In this case, the code block will be executed whenever the
expression inside If is evaluated to true, and the entire code block will be ignored whenever the
expression is evaluated as false.
When we use if, we should never place a semicolon after the parenthesis since doing so is not a
syntax error but a logic error. The compiler interprets this as if we want an empty statement to be
executed when if is met. If we see that the if statement is always fulfilled no matter how the
expression is evaluated, we may have this error.
In this case, seen here, the division is executed, and then the result is shown.
As we have placed the value zero in the divider, the division is not carried out.
It is always convenient to check the program execution and put values that can cause problems to
detect any logic error. We can test positive, negative, zero, fractional, and so on. If we encounter
problems with the values, we can use the if to validate the values before using them.
Here we can clearly see the If path and the Else path.
The code of our program would be composed as follows:
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Start the application here
static void Main(string[] args)
{
int number = 0; // Where we keep the number
string value = ""; // To save the string given by the use r
// We ask for the number
Console.Write("Give me an integer:");
value = Console.ReadLine();
number = Convert.ToInt32(value); // We convert the string to whole
// We use if with the expression for the case of positive if (number > = 0)
Console.WriteLine("The number {0} is positive", number); // I know
executes if number > = 0 is met else
Console.WriteLine("The number {0} is negative", number); // I
know executes if number > = 0 is NOT met
}
}
}
We can see that the program is simpler, and the logic has been simplified, which makes it easier
to read and maintain the program. But it does not mean that we should always use If-Else. We
have to use it when we have something that we want to execute fulfilling previously the specified
condition, and something that we want to execute when this one is not fulfilled. Abusing if-else
or using it senselessly will complicate the logic of the program, but using it well helps us.
It is always advisable to check the execution of the program and place values that may cause
problems to detect any logic errors. We can test positive, negative, zero, fractional values, etc. If
we find problems with the values, we can use the if to validate the values before using them.
If-Else Ladder
Another structure that can be used is the if-else ladder. One of its main functions is to optimize
the execution of the code. Sometimes they are necessary because the logic of the program
requires it. As with nested if, they should not be used without planning since not programming
them correctly can lead to logic errors that can be difficult to solve.
Now let's learn how we can use them to make our code more efficient. If we look at the program
of mathematical operations, we have an if for each operation. This means that when our program
runs, regardless of whether addition or multiplication has been selected, at least four if must
always be run—the If can be expensive operations since expressions have to be evaluated.
The way to optimize this is with an if-else string. The concept is simple and consists of putting
an If in the else statement.
Logical Expressions
Like arithmetic and relational expressions, logical expressions have their own operators. These
are: and, or and not.
Operator Meaning
&& And
|| or
! Not
Here we have the logical operators used in C #.
P Q P && Q
true true true
false true false
true false false
false false true
Suppose we have to decide whether we should fill the vehicle's gas tank. We do this if the tank is
less than 50% full and if the distance to be driven is more than 200 km. As we can see, we have
to use the conjunction since we have two conditions, and both of them must be met for the filling
of the gasoline to take place. If we place this as an expression, it would be:
if(tank < 50 && distance > 200)
Refueling
Suppose that tank is 25 and distance is 350 when evaluating 25 < 50 and 350 > 200; we have the
following.
if(true && true)
Refueling
In our table, we know that when both expressions are true, then the conjunction is fulfilled, and
the logical expression evaluates us to true.
if(true)
Refueling
So we'll get some gas.
Now let's assume that the tank is worth 90 and distance is again 350.
The first evaluations would give us:
if(false && true)
Refueling
When looking at our table, we see that false and true are evaluated as false, so we will not
perform the gasoline refueling.
It is easy to recall the conjunction; it is only true when both expressions are true. We can
remember the rule or simply have an impression of the table at hand. We must remember that
two expressions are needed, one on the right and the other on the left. With only one expression,
it is not possible to do this.
P Q P || Q
true true true
false true true
true false true
false false false
Let's look at an example with the disjunction. We have to take the umbrella if it rains or if there's
a lot of sunshine. The expression could look like this:
if(rain == true || lots of sunshine == true)
Take umbrella
Suppose there's rain but no sun, we'd have the expression:
if(true || false)
Take umbrella
In this case, if we look at the truth table, we can see that the result of evaluating the expression
gives us the truth, so we should take the umbrella.
Now let's see what happens if there is no rain and no sun. The expression would look like:
if(false || false)
Take umbrella
In this case, the expression is evaluated as false, and the umbrella is not taken.
It is easy to remember the truth table of disjunction. This is true when any of the expressions is
true. Since if one is true or the other is true, then the total expression is true. It's also nice that we
have this table on hand until we learn the memory disjunction.
p Negation
true false
false true
This means that if the right side operand is true, the operator returns false. And if the right-hand
operand is false, the operator returns true.
Let's look at an example to understand this better.
We have a room with an electric light bulb and suppose we have to turn on the light in the room
when it is not daylight. Then our expression looks like this:
if(!adi == true)
Turn on the light
Let's see what happens when the expression adi has as its true value. The expression adi == true
is evaluated as true and then denied, which in the end results in a false value. As if it receives the
value false, the command or method to turn on the light will be executed.
But if adi is false, then the expression adi == true is evaluated as false, which is denied, and the
If receives true. As the If is set to true, the light is turned on.
Now we can look at an example of how to make use of a logical expression. We can apply this to
our math operations program. We can observe that division must be done when the user has
selected among the options presented, the number 3, and the divisor has a value other than zero.
This is a case in which we can make use of the conjunction. If we proceed to modify the
application to do this, our flowchart should be modified, looking similar to the form we see
below:
We can see how the logical expression is inside the rhombus in the condition of the division.
The program code would look like this:
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Start the application here
static void Main(string[] args)
{
// Required variables
float a = 0.0f;
float b = 0.0f;
float result = 0.0f;
string value = "";
int option = 0;
// We show the menu
Console.WriteLine("1 - Sum");
Console.WriteLine("2- Subtraction");
Console.WriteLine("3- Division");
Console.WriteLine("4- Multiplication");
Console.Write("What operation do you want to do:");
value = Console.ReadLine();
option = Convert.ToInt32(value);
// We ask for the first number
Console.Write("Give me the first number:");
value = Console.ReadLine();
a = Convert.ToSingle(value);
// We ask for the second number
Console.Write("Give me the second number:");
value = Console.ReadLine();
b = Convert.ToSingle(value);
// We check for sum
if (option == 1)
result = a + b;
// We check for subtraction
else if (option == 2 )
result = a - b;
// We check for division else if (option == 3 && b! = 0)
// Here we use an expression logic result = a / b;
// We check for multiplication
else if (option == 4)
result = a * b;
// We show the result
Console.WriteLine("The result is: { 0}", result);
}
}
}
Let's see another example. Suppose we have to make a program that tells us if a person can drive
a car, and the conditions for driving it are that they are over 15 or 18 years old and that they have
permission from their parents. If we look at the problem, we see that we need two variables, one
for age and one for parental permission. The logical expression could be of the following form:
if (age> 18 || (age> 15 && permission == true))
Can drive
We see that in this case, we use a more complex expression. As with arithmetic expressions, we
have used parentheses to help us and make the logic easier to read. Our expression is a
disjunction, on the left side of the gold we have age> 18, on the right side we have an expression
(age> 15 && permission == true). The second expression is a conjunction and must be evaluated
first. The result obtained will be used by the disjunction. Now we can make the example program
for this expression. First, let's look at the flowchart below:
As in the previous case, we must place the expression within the rhombus regardless of its
complexity.
The program could look like this:
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Start the application her e
static void Main(string[] args)
{
// Required variables
int age = 0;
bool permission = false;
string value = "";
// We get the data
Console.Write("Give me the age:");
value = Console.ReadLine();
age = Convert.ToInt32(value);
Console.Write("You have parental permission (true / false): ");
value = Console.ReadLine();
permission = Convert.ToBoolean(value);
// We verify that the rule is fulfilled
if (age > 18 || (age > 15 && permission == true))
Console.WriteLine("It is possible to drive");
else
Console.WriteLine("You can't drive");
}
}
}
Denial simply swaps true for false and false for true. It is easy to remember. The value of the
right-hand operand is inverted. We must not forget that this operator only needs one operand,
and it is always on the right side. Failure to do so may cause problems with our program.
When we have complex expressions, to avoid errors, it is useful to make a truth table of the
expression and test all its cases. In this way, we can see if it works as we expected. The truth
table should be similar to the ones we have used, and we can lean on it to find the final value of
the expression.
Now we will learn to use another selective structure.
In real life, we sometimes repeat the same activity many times. Also, in computer programs, we
will see that it is necessary to repeat something many times. For this, we will make use of the
loops, which will make our code simpler while we can repeat an activity as many times as
necessary.
Here we can see how the loop was repeated, and the value of n was modified in each turn.
This is the result. Indeed, the control variable starts with 3. Of course, the number of repetitions
is less.
The control variable may have a negative value at initialization. This is useful when we need to
count from a negative number. Let's modify the For loop code as follows:
for (n = -10 n <= 10; n = n + 1)
Console.WriteLine (“{0}”, n);
The execution gives us the result that we can see in the following figure.
We can see that the path starts at -10. It should not be overlooked that the control variable also
passes through the value of zero.
Incremental Control
Now that we know how to place the range of the For loop from its start value to the value it will
count at, and we can start learning how to make use of the increment. Our increase has been one
at a time. However, we can make the count two by two, three by three, or any other value.
To accomplish this, we simply have to modify the increment and indicate how our control
variable would be increased. The value of the increment can be an explicitly placed value or the
value inside a variable. For example, let's make our loop advance by two.
for (n = 1; n <16; n = n + 2)
Console.WriteLine (“{0}”, n);
As we can see, we have now placed n = n + 2. With this, we indicate that 2 will be added to the
value of n with each turn of the loop. This is easier to understand if we look at the execution of
the program and see the display of the values of n.
We can see that the value of n increases by two for each turn of the loop.
The loops that we have used have always counted progressively, from the lowest value to the
highest value. But it is also possible to make a regressive loop. For example, we could make the
loop count from 10 to 1. For this, we need to modify not only the increment but also to put the
correct expressions in the initialization and the condition.
Let's see how to achieve this with the following statement:
for (n = 10; n>=1; n = n - 1)
Console.WriteLine(“{0}”, n);
Here we can observe how the value of n decreases one by one.
We can see how the request for the rating is repeated the number of times indicated.
An important point about this program, compared to the first attempt we made at the beginning
of the chapter, is that it can work with any number of students. It doesn't matter if it's 5, 10, or
5000; the program will do its job. We see how using the loop not only gives us flexibility but
also prevents us from having to repeat a lot of code.
Let's look at another example. We can use the For loop in any problem that needs something to
be repeated: an operation, a count, some process. But also the number of repetitions must be
known, either by an explicitly placed value or a value placed inside a variable.
Now we have to calculate the warp of a number. For example, the factorial of 5 is 5*4*3*2*1,
which gives 120. Similarly, we must calculate the factorial value of any number given by the
user. If we look at the problem and how it is solved, we can see that there is a loop, and this loop
is counting down. We can easily solve it with a for-loop that carries out the multiplication with
the control variable as the product.
This is the flow chart of the algorithm for calculating the factorial of a number.
The program code looks like this:
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Start the application here
static void Main(string[] args)
{
// Required variables
int n = 0; // Control variable
int number = 0; // Number to which we take factorial
int factorial = 1; // Factorial calculated
string value = "";
// We ask for the number
Console.WriteLine("Give me the number to get the factorial from:");
value = Console.ReadLine();
number = Convert.ToInt32(value);
// We calculate the factorial in the for loop (n = number; n> = 1; n) factorial
* = n;
// We show the result
Console.WriteLine("The factorial of {0} is {1}", number, factorial);
}
}
}
When we run the program, we find that we can carry out the factorial calculation without any
problem.
The factorial of the number is properly calculated.
This is the diagram of the do-while loop. We can observe its internal behavior.
Let's start cycling through the loop. First, we find the code to be carried out. This code is defined
inside a code block, even if it is only a statement. Generally, the code will modify in some way
the value of the variable or variables that we use for the expression in the condition. This value
change can be carried out through a calculation, process, or even a request to the user. Then we
have the condition to evaluate. In the condition, we place a logical or relational expression. If,
when evaluating the condition, we obtain the value true, then the code is repeated. In case the
false value condition is no longer repeated, and the program is continued. Keep in mind that
sometimes it happens that the condition is evaluated as false from the first time. In this case, the
code will only have been run once.
Let's see an example. We will create the carpentry program and use the do-while loop so that the
program repeats as many times as necessary, even without knowing how many times it is. To
achieve this, we have to think carefully about our condition and what is the state of the program
that we will evaluate in it.
The easiest way to do this is to ask the user if they want to do another conversion. If he does, the
code to convert is repeated. In case the user does not want it, the program ends. In this way, the
repetition of the loop is controlled and can be repeated, even without knowing how many times it
has to be done. Our program will have the following flowchart.
Here we can observe the programming and distinguish the do-while loop.
The program will be as follows:
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Start the application here
static void Main(string[] args)
{
// Required variables
float feet = 0.0f; // number of feet
float inches = 0.0f; // number of inches
float centimeters = 0.0f; // Result in centimeters
string response = ""; // Answer for another calculation
string value = "";
do
{
// We ask for the feet
Console.WriteLine("How many feet:");
value = Console.ReadLine();
feet = Convert.ToSingle(value);
// We ask for inches
Console.WriteLine("How many inches:");
value = Console.ReadLine();
inches = Convert.ToSingle(value);
// Convert to centimeters = ((feet * 12) + inches) * 2.54f;
// We show the result
Console.WriteLine("They are {0} centimeters", centimeters);
// We ask if another conversion
Console.WriteLine("Do you want to do another conversion (yes /
no)?");
response = Console.ReadLine();
} while (response == "yes") ;
}
}
}
In the execution, we can verify that we have a loop, but it can end whenever we want.
We can see that we have placed inside the loop the part of the conversion from feet and inches to
centimeters. After showing the result, we ask the user if he wants to make another conversion. If
so, we repeat the loop. If the user does not wish to make another conversion, the loop ends. This
allows us sometimes to repeat five times, when necessary ten, and so on depending on the user's
needs. We have solved the problem.
The do-while loop gives us extra flexibility, but it is always necessary to use the right type of
loop for the problem we have.
Let's look at another example where we can use this loop. In one of the previous programs, we
asked the user what operation he wanted to perform, and then we asked for the operands. The
program as it is is only executed once, but if we use the do-while loop and put a new option in
the menu, then the user can perform the operations that are needed or only one as it was used
before. This kind of behavior is very useful and easy to implement with the
If we modify the program, it will look like this:
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Start the application her e
static void Main(string[] args)
{
// Required variables
float a = 0.0f;
float b = 0.0f;
float result = 0.0f;
string value = "";
int option = 0;
// We have the loop
do
{
// We show the menu
Console.WriteLine("1 - Sum");
Console.WriteLine("2 - Subtraction");
Console.WriteLine("3 - Division");
Console.WriteLine("4 - Multiplication");
Console.WriteLine("5 - Exit");
Console.Write("What operation do you want to do:");
value = Console.ReadLine();
option = Convert.ToInt32(value);
if (option!= 5)
{
// We ask for the first number
Console.Write("Give me the first number:");
value = Console.ReadLine();
a = Convert.ToSingle(value);
// We ask for the second number
Console.Write("Give me the second number:");
value = Console.ReadLine();
b = Convert.ToSingle(value);
switch (option)
{
// We check for sum
case 1 :
result = a + b;
break;
// We check for subtraction
case 2:
result = a - b;
break;
// We check for division
case 3:
if (b!= 0) // this if is nested
result = a / b;
else // This else belongs to the second if
Console.WriteLine("Invalid Divider");
break;
// We check for multiplication
case 4:
result = a * b;
break;
// If none of the previous cases is fulfilled
default:
Console.WriteLine("Invalid option");
break;
}
// We show the result
Console.WriteLine("The result is: {0}", result);
}
} while (option!= 5);
}
}
}
Functions and methods are very important elements of programming. In C#, we will be using
them frequently, especially when we move towards object-oriented programming. Functions give
us many advantages and allow us to develop our applications faster and more orderly.
The Functions
Let's get to know the functions. Let's look at an example of a problem and then how using the
function can help us. The function is an element of the program that contains code and can be
executed; that means, it performs an operation. The function can be called or invoked when
necessary, and then the code inside it will be executed. Once the function is finished, the
program continues in the next instruction from which it was called.
We can observe how the execution of the program goes to the function and then returns to the
next sentence from where it was invoked.
The functions, to be useful, must be specialized. In other words, each function must do only one
thing and do it well. We have already used one function, it's the Main() function, and we can
create more functions as we need them. Within object-oriented programming classes have code,
and this code is found within functions called methods. For example, when we have converted
from a string to an integer, we make use of a function called ToIn32() that is inside the Convert
class.
The functions consist of five parts:
modifier type Name (parameters)
{
code
}
We will see the five parts now, but as we study the functions, we will know how they are used.
Functions can return information, and this information can be string, integer, floating, or any
other type. In the type section, we have to indicate precisely what kind of information is being
returned. If the function does not return any value, then we have to indicate its type as void.
All functions must be identified, and we do so by their name. The functions that we place inside
the classes must have a unique name. The name is also used to invoke or execute the function.
Functions may need data or information to work. We don't give this information through their
parameters. Parameters are nothing more than a list of variables that receive this data. If the
function doesn't need to use the parameters, then we can simply leave the brackets empty. We
should never forget to place the parentheses even if there are no parameters.
The code of the function is placed inside a block of code. In this section, we can place any valid
C# code, that is, variable declarations, cycles, selective structures, and even function invocations.
Functions, when declared, can have a modifier before the type. Modifiers change the way the
function works. We will be using a modifier known as static. This modifier allows us to use the
function without having to declare an object of the class to which it belongs.
We have four basic types of functions: those that only execute code, those that return values, and
those that receive parameters and receive values. During this chapter, we will get to know them.
Now that we know the basic elements of the functions, we can see an example of where their use
would be appropriate. Suppose we have a program in which, in different sections, we have to
write the same code, but due to its logic, we cannot use a cycle since it is in different parts of the
program. In this case, our only solution so far would be to rewrite the code simply.
Another way to solve it and avoiding repeated code is to use the function. The code that is going
to be used repeatedly is placed inside the function, and every time we need to use it, the function
is simply invoked. In our example of the carpenter, which we analyzed in the previous chapter,
we are in charge of making conversions from feet and inches to centimeters. The conversion was
done with a simple but rather long formula.
If now our carpenter needs a program to transform the measurements of a complete table into
centimeters, then we would have to use the right formula in several places. In order not to copy
the same code several times, the most convenient thing would be to place the formula in a
function and simply invoke it where necessary. Let's start to learn how to program and invoke
functions.
In the execution, we can observe how the code of the function is being executed.
Functions That Return a Value
Our next function type can return a value, and this means that when the function is called, it will
perform the execution of your code. The code will calculate a value somehow, and this value
calculated by the function will be returned to whoever invoked the function. The invocation may
have been made by the Main() function or some other function.
Since the function will return a value, we need to indicate its type. The type will depend on the
value returned. If the value is an integer, then the type of the function is int. If the value is a float,
then the function will have type float and so on. The function can return any of the types defined
in the language and also programmer-defined ti-pos and objects of different classes.
The function will use a special command to return the value; this command is known as a return
and is used as follows:
return variable;
As soon as the program execution finds a return, the function is terminated even if it has not
come to an end. At the same time that the function ends, the value co-located after the return is
returned to the one who called. The value can be placed with a variable or explicitly with a
particular value. Do not forget to put the semicolon at the end of the sentence. The end of the
function is carried out even if we have code written after the return.
Since the function returns a value, on the invoker side, we need to have someone who can
receive the returned value. Generally, we will use a variable, but in some cases, it can be an
expression that will be evaluated with the value returned by the function. Suppose our function
returns an integer value. So we can have a code like the following.
int n;
n = function ();
In this way, the value returned by the function is stored in the variable n, and we can make use of
it. We understand the code as follows. We have an integer variable n. Then we have an
assignment for n. If we remember, the assignment is always from right to left. The expression is
evaluated, and the function is executed and calculates a value, which is returned by return. This
value is considered to be the evaluation of the statement and is assigned to n. From this point on,
we can use the value as we need it.
Now we can start using this type of function in our application. For the subtraction operation, we
will make use of it. The code in the Main () part will not be so simple since we not only need an
invocation, we must receive a value and do something with it. In this way, in the if for
subtraction, we will obtain the value returned by the function and then present it to the user. The
Subtraction () function has the following flowchart.
We can see how the diagram of this function is created, not forgetting the return of the value.
The function code is as follows:
static float Subtraction()
{
// Required variables
float a = 0;
float b = 0;
float r = 0;
string number = "";
// We ask for the values
Console.WriteLine("Give me the first number");
number = Console.ReadLine();
a = Convert.ToSingle(number);
Console.WriteLine("Give me the second number");
number = Console.ReadLine();
b = Convert.ToSingle(number);
// We calculate the result
r = a - b;
// We return the result
return r;
}
We can see that the Subtraction () function is of float type, and in the end, we have placed the
return indicating the variable whose value we want to return, in our case r. But not only must we
add the function, but it is also necessary to put new code in the if that corresponds to the
subtraction.
// We check for the subtraction
if (option == 2)
{
// Variable for our result
float result = 0;
// We invoke and obtain the result
result = Subtraction();
// We show the result
Console.WriteLine("The result of the subtraction is
{0} ", result);
}
Let's run the program. We can see that the function acts as expected.
We see how the value returned by the function is displayed in who invoked it, in our case Main
().
The Multiplication() function is simpler, as it does not ask the user for data directly.
The function code is as follows:
static void Multiplication (float a, float b)
{
// Required variables
float r;
// We calculate the value
r = a * b;
// We show the result
Console.WriteLine ("The result is {0}", r);
}
As we can see, the function will have two parameters. The parameters are of the floating type
and are called a and b. Let's not forget that they are separated by a comma. The parameters a and
b will work as variables, and their content will be the values passed in the invocation.
The other place where we must add code in the Main() function, in this case, the if for
multiplication.
// We check for multiplication
if (option == 3)
{
// Required variables
float n1 = 0;
float n2 = 0;
string number = ””;
// We ask for the values
Console.WriteLine ("Give me the first number");
number = Console.ReadLine ();
n1 = Convert.ToSingle (number);
Console.WriteLine ("Give me the second number");
number = Console.ReadLine ();
n2 = Convert.ToSingle (number);
// We invoke the function
Multiplication (n1, n2);
}
Inside the If we create two floating variables and ask the user for the variables, we are going to
work with. These values are stored inside the variables n1 and n2. Now let's see the function
invocation. As the function was defined to receive parameters, then we must pass data in its
invocation. The parameters are placed between the parentheses. As we have it, the parameter a
will receive a copy of the value contained in n1, and the parameter b will receive a copy of the
value contained in n2. Now the function can carry out its work. The variables used in the
invocation don't need to be called like the parameters declared in the function. If needed, the
invocation could carry an explicitly placed value, for example:
// We invoke the function
Multiplication (n1, 4.0f);
When the function is invoked, the parameter a receives a copy of the value contained in n1, and
the parameter b receives the value of 4.
We see that the function prints the correct result, which shows us that it is receiving the
information passed on the parameters.
The division is carried out, and the return value usually shows the result.
With this, we already have a complete program.
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Here starts the application
static void Main(string[] args)
{
// Required variables
int option = 0;
string value = "";
// We show the menu
Console.WriteLine("1-Sum");
Console.WriteLine("2-Subtraction");
Console.WriteLine("3-Multiplication");
Console.WriteLine("4-Division");
// We ask for the option
Console.WriteLine("What is your option:");
value = Console.ReadLine();
option = Convert.ToInt32(value);
// We check for the sum
if (option == 1)
{
Sum();
}
// We check for the subtraction
if (option == 2)
{
// Variable for our result
float result = 0;
// We invoke and obtain the result
result = Subtraction();
// We show the result
Console.WriteLine("The result of the subtraction is {0} ", result) ;
}
// We check for multiplication
if (option == 3)
{
// Required variables
float n1 = 0;
float n2 = 0;
string number = "";
// We ask for the values
Console.WriteLine("Give me the first number");
number = Console.ReadLine();
n1 = Convert.ToSingle(number);
Console.WriteLine("Give me the second number");
number = Console.ReadLine();
n2 = Convert.ToSingle(number);
// We invoke the function
Multiplication(n1, n2);
}
// We check for division
if (option == 4)
{
// Required variables
float n1 = 0.0f;
float n2 = 0.0f;
float result = 0.0f;
string number = "";
// We ask for the values
Console.WriteLine("Give me the first number");
number = Console.ReadLine();
n1 = Convert.ToSingle(number);
Console.WriteLine("Give me the second number");
number = Console.ReadLine();
n2 = Convert.ToSingle(number);
// We invoke the functio n
result = Division(n1, n2);
// We show the result
Console.WriteLine("The result is {0}", result);
}
} // Main closure
static void Sum()
{
// Required variables
float a = 0;
float b = 0;
float r = 0;
string number = "";
// We ask for the values
Console.WriteLine("Give me the first number");
number = Console.ReadLine();
a = Convert.ToSingle(number);
Console.WriteLine("Give me the second number");
number = Console.ReadLine();
b = Convert.ToSingle(number);
// We calculate the result
r = a + b;
// We show the result
Console.WriteLine("The result is {0}", r);
}
static float Subtraction()
{
// Required variables
float a = 0;
float b = 0;
float r = 0;
string number = "";
// We ask for the values
Console.WriteLine("Give me the first number");
number = Console.ReadLine() ;
a = Convert.ToSingle(number);
Console.WriteLine("Give me the second number");
number = Console.ReadLine();
b = Convert.ToSingle(number);
// We calculate the result
r = a - b;
// We return the result
return r;
}
static void Multiplication(float a, float b)
{
// Required variables
float r = 0;
// We calculate the value
r = a * b;
// We show the result
Console.WriteLine("The result is {0}", r);
}
static float Division(float a, float b)
{
// Required variables
float r = 0;
// We check for division by zero
if (b == 0)
{
Console.WriteLine("Cannot divide by zero");
return 0.0f;
}
else
{
r = a / b;
return r;
}
}
}
}
The value of the variable is the same before and after the execution of the function.
When executing, we notice that the value of the variable is the same before and after invoking
the function. In other words, the function did not alter the value of the variable, although it
seemed that it would. Let's see the reason for this.
The first reason why this happens is that the variable was declared in the Main () function, that
is, only this function knows it and can use it directly. Main () is the scope of the variable. Then
we have that when the parameter is passed in this way, it is not actually the variable that is being
passed, but a copy of its value. So when our function tries to change the value, it changes to the
copy and not to the original variable.
When we pass the parameters in this way, we say that they go through a copy. But there is
another way to pass the parameters, and it is known as step by reference. Let's change our
program so that it is as follows:
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Here starts the application
static void Main(string[] args)
{
// Required variables
int number = 5;
// Value before function
Console.WriteLine("Value before function {0}",
number);
// We invoke function
Change(ref number);
// Value after function
Console.WriteLine("Value after function {0}",
number);
}
static void Change(ref int number)
{
// We change the value
number = 17;
}
}
}
Let's run the program first and then see what happens.
In this case, the value of the If variable changed; this is because the reference to the variable was
passed.
In this case, we are passing the parameter by reference. When this happens, instead of passing a
copy of the value, what we pass is a reference to where the variable is in memory. In this way,
any assignment to the variable is made on the original variable, and its value can be changed
even though it has been defined elsewhere.
To indicate that a parameter needs to be passed by reference, it is necessary to use the ref
statement, both in the invocation of the function and in its declaration. We can have more than
one variable passed by reference in a function.
Passing by reference is very useful, especially for cases when a function must return more than
one value. As we know, the return can only return one value. But by using references, we can
have a function that returns more than one value by modifying the passed variables.
Let's look at an example of this. We are going to create a function that allows exchanging the
values of two variables. This problem may seem simple, but without the use of references, it is
impossible to solve it with a single function. Next, we will see how our program is.
using System;
using System.Collections.Generic;
using System.Text;
namespace BaseApplication
{
class Program
{
// This is the main function of the program
// Here starts the application
static void Main(string[] args)
{
// Required variables
int a = 5;
int b = 3;
// Value before function
Console.WriteLine("Values before function a = {0}, b = {1}", a, b);
// We invoke function
Change(ref a, ref b);
// Value after function
Console.WriteLine("Values after function a = {0}, b = {1}", a, b);
}
static void Change(ref int x, ref int y)
{
// working variable
int temp = 0;
// We change the value
temp = x;
x = y;
y = temp;
}
}
}
If we run it, we get the following:
The values have been exchanged for the function.
As we can see, we make use of a working variable to help us in the interchange of values. The
step by reference allows us to modify both variables.
A few years ago, programming for Windows was complicated and required a high degree of
specialization. The .NET Framework solves many of the problems related to Windows
programming and interoperability. .NET applications are compiled to an assembly that contains
the program written in CIL.
This is an intermediate language that the runtime reads when the application is run. The CLR
compiles the CIL for the microprocessor as needed; the use of a runtime gives .NET the
flexibility of being cross-platform. All .NET languages must comply with the guidelines found in
the CLS.
The most important point about C #: it is a modern programming language. It simplifies and
modernizes C ++ in the areas of classes, namespaces, method overloading, and exception
handling. The screen abandons the complexity of C ++, making it easier to use and less error-
prone.
Contributing to C # 's ease of use is the reduction of some C ++ features, and no longer macros,
templates, and multiple inheritances. Especially for enterprise developers, the above features will
only produce more trouble than benefits. New features that make programming easier are strict
type safety, version control, garbage collect, and more. The goal of all these functions is to
develop component-oriented software.
Your effort to learn C # is a big investment because C # is designed for the primary language of
writing NGWS applications. You will find a lot of functions that you can achieve or laboriously
implement in C ++, which are just some basic functions in C #. For enterprise-level
programming languages, new financial data types are popular. You use a new decimal data type
that is dedicated to financial calculations. If you don't like this simple ready-made type, you can
easily create a new data type based on the special needs of your application.
Wouldn't you expect a new language not to support object-oriented features? C # certainly
supports all key object-oriented concepts, such as encapsulation, inheritance, and polymorphism.
The complete C # class pattern is built on top of the Virtual Object System (VOS) of the NGWS
runtime. VOS will be described in the next chapter. The object pattern is only part of the
foundation and is no longer part of the programming language.
The first thing you must focus on is that there are no more global functions, variables, or
constants. Everything is encapsulated in the class, including case members (through the class's
case-objects are accessible) or static members (through data types). These make C # code more
readable and help reduce potential naming conflicts.
The C # language evolved from C and C ++. It was created for enterprise developers who are
willing to sacrifice a bit of low-level features of C ++ to get more convenient and productive. C #
is modern, simple, object-oriented, and type-safe. Although it borrows a lot from C and C ++,
there are still huge differences between specific areas such as namespaces, classes, methods, and
exception handling.
C # provides you with convenient functions such as garbage collection, type safety, version
control, and so on. The only "cost" is that code operations are type-safe by default, and pointers
are not allowed. It's all about type safety. However, if you need pointers, you can still use them
with non-secure codes, and you cannot have column sets when calling non-secure codes.
Resources
https://docs.microsoft.com/en-us/dotnet/csharp/getting-started/
https://docs.microsoft.com/en-us/visualstudio/get-started/csharp/tutorial-aspnet-core
https://dotnet.microsoft.com/learn/dotnet/in-browser-tutorial/1
https://csharp.net-tutorials.com/
https://www.homeandlearn.co.uk/csharp/csharp.html
https://study.com/academy/lesson/5-basic-elements-of-programming.html
http://www.cs.fsu.edu/~cop3014p/lectures/ch2/index.html
http://ineasysteps.com/essential-elements-program/
https://overiq.com/c-programming-101/basic-elements-of-a-c-program/
https://theory.uwinnipeg.ca/programming/node3.html
https://www.studytonight.com/c/decision-making-in-c.php
https://www.w3schools.in/c-tutorial/decision-making/
https://www.programiz.com/c-programming/c-decision-making-loops-examples
https://www.techbeamers.com/c-decision-making/
https://www.tutorialspoint.com/cprogramming/c_for_loop.htm
https://www.programiz.com/c-programming/c-for-loop
https://beginnersbook.com/2014/01/c-for-loop/
https://intellipaat.com/blog/tutorial/c-tutorial/c-loops/
https://www.tutorialcup.com/cprogramming/decision-making-and-loops.htm
https://beginnersbook.com/2014/01/c-functions-examples/
https://www.geeksforgeeks.org/functions-in-c/
https://www.programiz.com/c-programming/c-functions
https://www.tutorialgateway.org/types-of-functions-in-c/
https://www.csharpstar.com/c-program-to-perform-all-basic-arithmetic-operations/
https://www.sanfoundry.com/csharp-programs-perform-arithmetic-operations/
C#
Simple and Effective Tips and Tricks to Learn C#
Programming Effectively
BENJAMIN SMITH
Introduction
This book contains proven steps and strategies on how to program in C# or C Sharp. This book
will help you learn the basics of C# programming simply and effectively. I have written and
tested all the code samples that I have included in the book. You have the permission to copy the
code and paste in the editor or compiler to see the results. I recommend that in the first attempt
you should copy and paste the code to have a feel of how you a program in C# looks like. When
you think that you have acquired sufficient knowledge and have also refurbished your
programming skills, you can edit the sample codes by changing variable names, class names,
values of the integers, and add more class instances. Afterward, you can compile the code and
see the results.
You should not worry if you don’t see the desired results and see an error message instead. I
have dedicated a comprehensive section on what possible errors you may come across during the
programming phase and what the error message will look like. All you need is to study the error
message and understand its context. Then you can easily remove the errors and streamline the
code. When you have gained expertise in reading and understanding the error messages, you will
make fewer errors.
C# programming language is a powerful language. It is relatively mature and is a descendant of
C and C++. It also retains certain features of the Java language. Programming with C# is great
fun. Microsoft created C# as a part of the .NET initiative. This book will explain the ins and outs
of C# programming language. You will learn how to write usable programs. For which purpose,
you will need a particular coding environment. We bet that most of the readers will definitely use
Microsoft Visual Studio. There are alternatives that you can lay your hands on.
I learned to program when I was in high school. I didn’t study programming in the school or
college. Instead, I learned it by reading a bunch of good books and practice. My love for coding
started with an incident. I used to study history at school. Like all the other teenagers, I was in
love with my computer and the internet. One day I was coming back from school to home. It was
a dull afternoon. The sky had gone behind thick clouds when I put my car on the highway. It was
a beautiful sight and scary too. The line of trees along the edge of the road had starts swaying
back and forth being pushed by gusts of wind. I knew a storm was likely to hit the town. And it
did. It went dark suddenly. I was afraid, to say the least. It rained heavily that afternoon. The
wind smashed the car windows but I kept driving until I got out of the storm. I reached home by
evening only to find that my system applications had been shattered in a hacking attack. I used to
run an online application that I had got developed by a friend. I wondered if he would develop
the same from scratch again. He refused to cite the reason that he had been busy in research
work. I was disappointed, to say the least. He ruined my life.
That day I decided to take over the control of developing my applications. I learned C# along
with other programming languages and I found it the best out of all of them. My craze for coding
didn’t stop there but it increased several folds. I built one after another application and also sold
some to fellow students.
The C# programming language is one of the languages that programmers use to build executable
programs. C# is a powerful object-oriented language. It is open-source, modern, simple, and
flexible, and is also quite a versatile language. A programming language is something that you
can use to write software programs. C# is a simple language that also supports modern-day
functionality for different types of software development. C# was designed in the first place to
help enterprises and businesses. It caters to all of their needs. It was designed to build different
software for businesses. C# provides much-needed functionality to support modern-day software
development. It supports mobile and web app development.
C# is open source under .NET Foundation. Microsoft governs and runs the foundation. C#
language compilers, specifications, and tools can be found as open-source projects on GitHub.
C# is flexible as the programs built with it can be executed on the current machine or they can
simply be transmitted on the Web. You also can execute them on some distant computer. C# is
powerful because it has the same command set as that of C++. It error-proofs the commands that
are responsible for several C++ errors so that you spend less time chasing them down.
The .NET code library that C# uses for its capabilities offers the help that is needed to create
complicated display frames, including drop-down lists, grouped buttons, background images,
tabbed windows, and scroll bars. C# tends to play a pivotal role in the .NET Framework.
Saving Code
When you have written code, you can save it in a handy location to use in the future. That
location is the Toolbox window. You have to follow these steps. In the Main() method of the
class Program, you need to select the lines you have to save. Open the Toolbox window. Open it
by choosing View and then click on Toolbox. Now drag the selected lines in the General tab onto
the Toolbox window and drop the same. You can, anytime, reuse the code in the future.
Chapter Two
Getting Started With C#
The most basic concept is of variables in all programming languages. A C# variable, like that of
other languages, is a small container that stores different things like numbers. The term variable
comes from mathematics. In C# there are several limitations for programmers when it comes to
using them to building programs. This chapter will walk you through the world of variables. You
will learn how to declare them, initialize them, and use them in C#.
You might have learned in the third grade the equation x = 1. By writing the equation, you are
declaring a variable. You are saying that the variable x has the value ‘1.’ In the world of
programming, you first have to define a variable in a specific way.
C# has different types of variables. The variable ‘int’ is used to store integers like whole
numbers without decimals. The variable ‘double’ is used to store floating-point numbers such as
20.67. The variable ‘char’ is used to store single characters such as ‘x’. You have to surround the
char values within single quotes. The variable ‘bool’ is used to store values with two states such
as false or true. The variable ‘string’ is used to store pieces of text; you will have to store string
values by double-quotes.
If you want to create a variable, you must specify its type and its value as well. Assign the
variable a name such as x and add an equal sign if you want to assign values to the variable. See
the following variable that should store text.
using System.IO;
using System;
class myProgram
{
static void Main(string[] args)
{
string sentence = "This is a C# program. I am creating a string by filling it in
with a particular value!";
Console.WriteLine(sentence);
}
}
$mcs *.cs -out:main.exe
$mono main.exe
This is a C# program. I am creating a string by filling it in with a particular value!
In the following example, I will create a variable named thisNum in which I will store a number.
Take a look at the following example. I will create a variable named thisNum of int type. Will
also assign it a numeric value.
using System.IO;
using System;
class myProgram
{
static void Main(string[] args)
{
int thisNum = 22;
Console.WriteLine(thisNum);
}
}
$mcs *.cs -out:main.exe
$mono main.exe
22
You also can create a variable first and assign the value later. See the following example.
using System.IO;
using System;
class myProgram
{
static void Main(string[] args)
{
int thisNum;
thisNum = 50;
Console.WriteLine(thisNum);
}
}
$mcs *.cs -out:main.exe
$mono main.exe
50
If you have already assigned a value to a variable but you once again assign it in the next line,
the previous value will be overwritten by the latest value.
using System.IO;
using System;
class myProgram
{
static void Main(string[] args)
{
int thisNum = 25;
thisNum = 50;
Console.WriteLine(thisNum);
}
}
$mcs *.cs -out:main.exe
$mono main.exe
50
C# Strings
A string is a class for which C# tends to offer special treatment because strings are widely used
in several programs. The keyword string is often confused with String. In the following example,
I will analyze different elements of a string.
using System.IO;
using System;
class myProgram
{
static void Main(string[] args)
{
String sentence = "This is a C# program. I am creating a string by filling it in
with a particular value!";
Console.WriteLine(sentence);
}
}
In this example, a sentence is an object of the class String. If we convert the uppercase of S into
lowercase, it will be a simple string. However, string or String is compatible with each other.
Once you have created a string object, you cannot change or modify it. C# lacks an operation
that tends to modify the string object. If you modify it, you will get a new object in return. That’s
how one string becomes two.
using System.IO;
using System;
namespace ModifyString
{
class Program
{
public static void Main(string[] args)
{
// I am now Create a brand student object.
newStudent s1 = new newStudent();
s1.Name = "Tom";
// Now I will make another new object that has the same name.
newStudent s2 = new newStudent();
s2.Name = s1.Name;
s2.Name = s1.Name.ToUpper();
Console.WriteLine("s1 - " + s1.Name + ", s2 - " + s2.Name);
Console.WriteLine("You are required to Press the Enter button to terminate...");
Console.Read();
}
}
class newStudent
{
public String Name;
}
}
$mcs *.cs -out:main.exe
$mono main.exe
s1 - Tom, s2 - TOM
You are required to Press the Enter button to terminate...
The ToUpper didn’t change the name. However, it created an independent uppercase string and
the stores the same in the new object s2. This property of strings is also known as the
immutability of unchangeability. It is important for string constants. As a C# programmer, you
will get to perform multiple operations on strings. Every program tends to use an additional
operator that you can use on strings. In the following example, I will use the + data operator to
concatenate different pieces into one.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string name = "Tom";
Console.WriteLine("I was pleased to meet him. His name was " + name + ".");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
I was pleased to meet him. His name was Tom.
Comparison of Strings
It is quite common to compare two strings. If you want to know whether two strings are equal in
length or not, you can use the == operator to confirm. To see if they are unequal or not, you
should use the inverse operator !=.
String Length
A string in C# language is an object, which contains methods and properties that would perform
several operations on strings. For example, you can find the length of a string by using the
Length property.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence = "I am learning C Sharp. It is an interesting object-oriented
language.";
Console.WriteLine("The length of the above mentioned string is: " +
sentence.Length);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The length of the above mentioned string is: 68
String Methods
There are different string methods that you can use. To name a few, you can convert strings into
uppercase and lowercase by using some simple methods.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence = "I am learning C Sharp. It is an interesting object-oriented
language.";
Console.WriteLine(sentence.ToUpper());
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
I AM LEARNING C SHARP. IT IS AN INTERESTING OBJECT-ORIENTED LANGUAGE.
The above method converted the string to upper case. The following method will convert the
string into the lower case. See the example.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence = "I am learning C Sharp. It is an interesting object-oriented
language.";
Console.WriteLine(sentence.ToLower());
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
i am learning c sharp.it is an interesting object-oriented language.
There is a method to concatenate two strings. I will use the + operator to combine two strings
into a single whole. See the following example for details.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence1 = "I am learning C Sharp." ;
string sentence2 = "It is an interesting object-oriented language.";
string fullsen = sentence1 + sentence2;
Console.WriteLine(fullsen);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
I am learning C Sharp. It is an interesting object-oriented language.
You can display the concatenated result in upper case as well by adding a simple method.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence1 = "I am learning C Sharp.";
string sentence2 = "It is an interesting object-oriented language.";
string fullsen = sentence1 + sentence2;
Console.WriteLine(fullsen.ToUpper());
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
I AM LEARNING C SHARP. IT IS AN INTERESTING OBJECT-ORIENTED LANGUAGE.
Now I will convert it into lowercase by adding the relevant method.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence1 = "I am learning C Sharp.";
string sentence2 = " It is an interesting object-oriented language.";
string fullsen = sentence1 + sentence2;
Console.WriteLine(fullsen.ToLower());
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
i am learning c sharp. it is an interesting object-oriented language.
String concatenation can also be done by using a dedicated concatenation method instead of the
+ operator. The method namely string.Concat() can be used to achieve the same goal.
using System.IO;
using System;
namespace MyApplication
{
class Progra m
{
static void Main(string[] args)
{
string sentence1 = "I am learning C Sharp.";
string sentence2 = " It is an interesting object-oriented language.";
string fullsen = string.Concat (sentence1, sentence2);
Console.WriteLine(fullsen.ToUpper());
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
I AM LEARNING C SHARP. IT IS AN INTERESTING OBJECT-ORIENTED LANGUAGE.
Another method for string concatenation is string interpolation, which substitutes the values of
different variables into placeholders in the string. You should note that you don’t have to worry
about the spaces as is the case with concatenation.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence1 = "I am learning C Sharp.";
string sentence2 = " It is an interesting object-oriented language.";
string fullsen = $"{sentence1} {sentence2}" ;
Console.WriteLine(fullsen.ToUpper());
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
I AM LEARNING C SHARP. IT IS AN INTERESTING OBJECT-ORIENTED LANGUAGE.
Access String
There is a method to access different characters in a string by referring to the index number
which is inside the square brackets.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence1 = "I am learning C Sharp.";
string sentence2 = " It is an interesting object-oriented language.";
Console.WriteLine(sentence1[9]);
}
}
}
$mcs *.cs -out:main.exe
Compilation succeeded - 1 warning(s)
main.cs(11,14): warning CS0219: The variable `sentence2' is assigned but its value is
never used
$mono main.exe
n
The compiler has issued a warning because I left the second string without assigning any method
to it. Let’s access a character in the second string.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence1 = "I am learning C Sharp.";
string sentence2 = " It is an interesting object-oriented language.";
Console.WriteLine(sentence1[10]);
Console.WriteLine(sentence2[15]);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
i
e
There is a reverse method by which you can locate the index number of each character in a
string. All you have to do is to enter the alphabet of the string and C# will find the index number
linked to that alphabet. There is a specific method for the purpose, called the IndexOf() method. I
will use the same strings to test this method and see how effective it is when you are creating a
program.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence1 = "I am learning C Sharp.";
string sentence2 = " It is an interesting object-oriented language.";
Console.WriteLine(sentence1.IndexOf("S"));
Console.WriteLine(sentence2.IndexOf("t"));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
16
2
Substrings
There is another useful method known as Substring() which extracts several characters from a
particular string. You can decide the specified character position and the method will come up
with a new substring. I will use this method in combination with IndexOf() to find out the
specific character position.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence2 = " It is an interesting object-oriented language.";
int charPos = sentence2.IndexOf("o");
Console.WriteLine(sentence3);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
object-oriented language.
In the next example, I will choose another point from where I will slice off the substring. I will
enter ‘i’ as the point from which the program should slice off the string and create a substring.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence2 = " It is an interesting object-oriented language." ;
int charPos = sentence2.IndexOf("i");
Console.WriteLine(sentence3);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
is an interesting object-oriented language.
The results were not as I had intended. I wanted to create the string starting from the word
‘interesting.’ However, the word ‘is’ also starts from the word ‘i’ and this came before the word
‘interesting’. As such the substring was created from the same word. There is a solution to this
problem. I will add another alphabet from the word interesting and expect the desired results.
Another alphabet from the desired word will add clarity to the program and the compiler will
find it easy to locate the desired word.
using System.IO;
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
string sentence2 = " It is an interesting object-oriented language.";
int charPos = sentence2.IndexOf("in") ;
Console.WriteLine(sentence3);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
interesting object-oriented language.
Array Length
You can check the length of the array by using the following code. Let’s try it.
using System;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
string[] fruits = {"guava", "grapefruit", "apple", "banana", "strawberry",
"blueberry", "jackfruit", "dragonfruit", "peach", "apricot"};
Console.WriteLine(fruits.Length);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
10
Array Loop
C# gives you the option of looping through the array elements with a for loop. You also can use
the Length property for specifying how many times the loop should run. The following example
will loop through all elements of fruits array.
using System;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
string[] fruits = {"guava", "grapefruit", "apple", "banana", "strawberry",
"blueberry", "jackfruit", "dragonfruit", "peach", "apricot"};
for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine(fruits[i]);
}
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
guava
grapefruit
apple
banana
strawberry
blueberry
jackfruit
dragonfruit
peach
apricot
If you change the symbol of less than to greater than, you will not have any results.
using System;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
string[] fruits = {"guava", "grapefruit", "apple", "banana", "strawberry",
"blueberry", "jackfruit", "dragonfruit", "peach", "apricot"};
for (int i = 50; i > fruits.Length; i++)
{
Console.WriteLine(fruits[i]);
}
}
}
}
The result will be an empty page. You also can change the value of i and the looping will be
limited. This can be handy in case you create a program for which you want the users to see only
a few elements.
using System;
using System.Collections.Generic;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
List<string> fruits = new List<string>();
// add fruits
fruits.Add(" apple ");
fruits.Add(" banana ");
fruits.Add(" orange ");
fruits.Add(" plum ");
fruits.Add(" guava ");
fruits.Add(" melon ");
fruits.Add(" watermelon ");
fruits.Add(" strawberry ");
fruits.Add(" blueberry ");
fruits.Add(" jackfruit ");
fruits.Add(" dragonfruit ");
// now remove the banana
fruits.Remove("banana");
Console.WriteLine(fruits.Count) ;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
11
Item Removal
If you want to remove items from a list, you can use another method for the purpose. If you are
creating a program in which a vendor sells fruit, you can write in such a way that whenever the
vendor sells out a particular fruit, the player will be able to remove the empty cart from the shop
by using the index number of the fruit.
using System;
using System.Collections.Generic;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
List<string> fruits = new List<string>();
fruits.Add(" apple ");
fruits.Add(" banana ");
fruits.Add(" orange ");
fruits.Add(" plum ");
fruits.Add(" guava ");
fruits.Add(" melon ");
fruits.Add(" watermelon ");
fruits.Add(" strawberry ");
fruits.Add(" blueberry ");
fruits.Add(" jackfruit ");
fruits.Add(" dragonfruit ");
fruits.RemoveAt(1);
fruits.RemoveAt(5);
Console.WriteLine(fruits.Count);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
9
C# Lists
C# has been fun to code in and one reason behind this is lists. This post will tell you how you can
fill items into a list. You can add, sort or remove different items from a list. C# has indexed lists
and like the arrays the index starts at 0. The items are not sorted. While an array has a fixed size,
the items in a list can be changed at will, which is why a list is the perfect choice if you don’t
know the number of items that you must include in it. It is estimated that you can pack up about
two million elements in a list if you are operating a 64-bit operating system.
using System;
using System.Collections.Generic;
class Program1 {
// Main Method
public static void Main(String[] args)
{
class Program1 {
// Main Method
public static void Main(String[] args)
{
flist.Add(5);
flist.Add(6);
class Program1 {
// Main Method
public static void Main(String[] args)
{
Console.WriteLine(flist.Contains(5));
}
}
$mcs *.cs -out:main.exe
$mono main.exe
True
If the digit is not present, the result will be different.
using System;
using System.Collections.Generic;
class Program1 {
// Main Method
public static void Main(String[] args)
{
Console.WriteLine(flist.Contains(50));
}
}
$mcs *.cs -out:main.exe
$mono main.exe
False
Here is another example of list creation by using C#.
using System;
using System.Collections.Generic;
class Program1 {
int p = 0;
Console.WriteLine(" ");
flist.RemoveAt(3);
int p1 = 0;
foreach(int n in flist)
{
Console.Write("now I am at Position {0}: ", p1);
Console.WriteLine(n) ;
p1++;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Take a look the elements present in the List:
We are at Position 0: 17
We are at Position 1: 19
We are at Position 2: 21
We are at Position 3: 9
We are at Position 4: 75
We are at Position 5: 19
We are at Position 6: 73
I am removing the element at the index 3
At Position 0: 17
At Position 1: 19
At Position 2: 21
At Position 3: 75
At Position 4: 19
At Position 5: 73
List Creation
You can create a list of fruits and count the numbers by using the following method. See the
example below.
using System;
using System.Collections.Generic;
class Program1 {
class Program1 {
C# conditional statements generally are used when you have to execute or simply test a
particular action depending on a specific condition. C# allows programmers to test multiple
conditions. You can apply certain logical conditions from mathematics. You can test conditions
like less than, less than or equal to, equal to, greater than, greater than or equal to, and not equal
to. These conditions can be used to perform different actions to make different decisions. Just
like other programming languages C# can test a number of conditions like if, else if, else and
switch.
Let’s try a simple condition using the if condition. The condition will be true if the number
before the greater than sign is greater than 18. If not, the condition will be false.
using System.IO;
using System;
class Program1
{
static void Main()
{
if (50 > 18)
{
Console.WriteLine("The Number 50 is greater than 20");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The Number 50 is greater than 20
Now I will change the values and see what happens. If we put a lower number before the greater
than sign, the result will be a compilation error.
using System.IO;
using System;
class Program1
{
static void Main()
{
if (50 > 60)
{
Console.WriteLine("The Number 50 is greater than 60");
}
}
}
$mcs *.cs -out:main.exe
Compilation succeeded - 1 warning(s)
main.cs(10,9): warning CS0162: Unreachable code detected
$mono main.exe
In the following examples, I will test and see the results of other conditions I have talked about at
the start of the topic. The first on the line is the less than sign. It will show a simple message that
a particular number is less than the other one. See the following example. All you need to do is
to change the greater than sign to less than, and also change the statement.
using System.IO;
using System;
class Program1
{
static void Main()
{
if (50 < 60)
{
Console.WriteLine("The Number 50 is less than 60");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The Number 50 is less than 60
The next is the less than or equal to sign. I will also change the statement that will be displayed
to the user.
using System.IO;
using System;
class Program1
{
static void Main()
{
if (60 <= 60)
{
Console.WriteLine("The Number 50 is less than or equal to 60");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The Number 50 is less than or equal to 60
The conditional is the ‘greater than’ or ‘equal to’ option. I will change the sign and the statement
that will be printed by the compiler. See how it works.
using System.IO;
using System;
class Program1
{
static void Main()
{
if (70 >= 60)
{
Console.WriteLine("The Number 70 is less than or equal to 60");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The Number 70 is less than or equal to 60
In the next code snippet, I will make sure that the two numbers are equal.
using System.IO;
using System;
class Program1
{
static void Main()
{
if (60 >= 60)
{
Console.WriteLine("The Number 60 is less than or equal to 60");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The Number 60 is less than or equal to 60
There is another option that tells whether a number is equal to a number or not. It checks the
condition and displays the result in the form of a statement. The sign you will use for the purpose
is ==. I will replace the sign and change the statement to put this to work.
using System.IO;
using System;
class Program1
{
static void Main()
{
if (60 == 60)
{
Console.WriteLine("The Number 60 is equal to 60");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The Number 60 is equal to 60
There is a separate operator to check if two numbers are unequal or not. You will have to replace
the == sign with != and check out the results. See the following code snippet.
using System.IO;
using System;
class Program1
{
static void Main()
{
if (70 != 60)
{
Console.WriteLine("The Number 70 is not equal to 60");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The Number 70 is not equal to 60
Now that we have tested all the operators that you will have to use while writing conditional
statements, you can move on to practicing the first conditional statement that is the if statement.
You have seen the simplest use of the if statement. One thing to keep in mind is that you always
have to write if in lowercase letters. If you write it in uppercase letters, it will generate an error.
Let’s see how the error will look like if you change the case of letters.
using System.IO;
using System;
class Program1
{
static void Main()
{
If (70 != 60)
{
Console.WriteLine("The Number 70 is not equal to 60");
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 1 error(s), 0 warnings
main.cs(9,6): error CS1525: Unexpected symbol `{'
Now I will change both letters to uppercase.
using System.IO;
using System;
class Program1
{
static void Main()
{
IF (70 != 60)
{
Console.WriteLine("The Number 70 is not equal to 60");
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 1 error(s), 0 warnings
main.cs(9,6): error CS1525: Unexpected symbol `{'
You can see that in both attempts, the compilation failed and we had an error. One of the most
interesting features of the conditional statements is that it allows you to test different variables
and the condition between them. I will fill in the program with two variables a and b, and then I
will test them using different conditions that I have already mentioned.
using System.IO;
using System;
class Program1
{
static void Main()
{
int a = 30;
int b = 28;
if (a > b)
{
Console.WriteLine("The variable a is greater than b.");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The variable a is greater than b.
In the next code snippet, I will use the >= operator.
using System.IO;
using System;
class Program1
{
static void Main()
{
int a = 30;
int b = 28;
if (a >= b)
{
Console.WriteLine("The variable a is greater than b.");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The variable a is greater than b.
In the next example, I will use the less than operator on the same equation and the result will be
an error.
using System.IO;
using System;
class Program1
{
static void Main()
{
int a = 30;
int b = 28;
if (a < b)
{
Console.WriteLine("The variable a is greater than b.");
}
}
}
The result will be empty or an error as the compiler will be unable to process the information. In
the above examples, I have used two variables a and b to test if a is greater than b by using the
operator >. Then I wrote a statement that the program printed after testing the condition.
The Else Statement
You can use the else statement for specifying a certain block of code that you can execute if the
condition stands false. There are two blocks of code in the if-else statement. If the condition is
true, the first block of code executed. If the condition is false, the second block of code is
executed. In the following example, I will write a simple if-else statement that reads the time, test
the condition and displays a greetings message for the user. You can use this simple program in
your office or the reception of your business.
using System;
using System.Collections.Generic;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
int time = 15;
if (time < 16)
{
Console.WriteLine("Good day.");
}
else
{
Console.WriteLine("Good evening.");
}
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Good day.
In this example, the second block of code is executed because the condition turned out to be
false. In the next block of code, I will test the first block of code.
using System;
using System.Collections.Generic;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
int time = 18;
if (time < 16)
{
Console.WriteLine("Good day.");
}
else
{
Console.WriteLine("Good evening.");
}
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Good evening.
C# is an interesting language when it comes to writing a program that welcomes user input. You
have read about C# variables. These variables are used to store different types of input that is
entered by different users. This chapter will walk you through the process of accepting input
from users, storing data in a variable and then displaying different messages to the users. If you
want to display messages to users, you can use the Write() or WriteLine() methods that are built-
in in the C# language. Although the function of both methods is the same, the major difference
between the two is that they WriteLine() brings the cursor down to the next line after it has
displayed the message. The other method doesn’t give any such privilege to the users.
User Input
You have learned how to write Console.WriteLine() to display different types of output in a
program. There is another feature in C# that you can use to read input by a user. I will be using
Console.ReadLine() to receive the user input. This feature is very helpful for creating a program
that needs users to enter the input. The input is then stored in a variable. The program will then
print the value of the variable.
using System;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
// You are required to type the username and then press enter
Console.WriteLine("Please Enter the username: Jack");
// Now I will create a variable to store user input from your keyboard
string usrName = Console.ReadLine();
// Now I will print the value of this newly created variable, which will display this
input value
Console.WriteLine("The desired username is: " + usrName);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Please Enter the username: Jack
The desired username is:
Numerical Input
In the above program, the input type was string. The Console.ReadLine() will return a string. As
I have specified it, I will not be able to get value from another data type such as int. You can use
the following method to receive numerical input.
using System;
namespace MyApp
{
class Program1
{
static void Main(string[] args)
{
Console.WriteLine("You are required to enter your age:");
int yourage = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Your age is: " + yourage);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
You are required to enter your age: 56
Your age is: 0
C# Switch Statement
By using a switch statement, you can test a variable against values that you have allocated to a
list. Values are dubbed as cases, and the variable that is switched on is verified for switch case.
There are some rules that you must follow when you are writing switch statements.
The expression in a switch statement ought to be an integral type. There is no limit to the number
of cases in a switch. You should make sure to insert a colon to the end of each case. The
constant-expression and variable must be of the same data type in a switch. If the variable is
equal to the case, the execution will continue to the point you have included the break statement
in the code. The break statement terminates the switch. If you have forgotten to include a break
statement, you will see a compilation error. You must include a default case at the end of the
switch statement.
using System.IO;
using System;
class Program
{
static void Main()
{
int day = 1;
switch (day)
{
case 1:
Console.WriteLine("We will start construction of the office on Monday");
break;
case 2:
Console.WriteLine("We will start construction of the office on Tuesday");
break;
case 3:
Console.WriteLine("We will start construction of the office on Wednesday");
break;
case 4:
Console.WriteLine("We will start construction of the office on Thursday");
break;
case 5:
Console.WriteLine("We will start construction of the office on Friday");
break;
case 6:
Console.WriteLine("We will start construction of the office on Saturday") ;
break;
case 7:
Console.WriteLine("We will start construction of the office on Sunday");
break;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
We will start construction of the office on Monday
I will enter different values to see how the switch statement executes different blocks of code
from the program.
using System.IO;
using System;
class Program1
{
static void Main()
{
int day = 3;
switch (day)
{
case 1:
Console.WriteLine("We will start construction of the office on Monday");
break;
case 2:
Console.WriteLine("We will start construction of the office on Tuesday");
break;
case 3:
Console.WriteLine("We will start construction of the office on Wednesday") ;
break;
case 4:
Console.WriteLine("We will start construction of the office on Thursday");
break;
case 5:
Console.WriteLine("We will start construction of the office on Friday");
break;
case 6:
Console.WriteLine("We will start construction of the office on Saturday");
break;
case 7:
Console.WriteLine("We will start construction of the office on Sunday");
break;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
We will start construction of the office on Wednesday
I will try a different value in the next example.
using System.IO;
using System;
class Program1
{
static void Main()
{
int day = 5;
switch (day)
{
case 1:
Console.WriteLine("We will start construction of the office on Monday");
break;
case 2:
Console.WriteLine("We will start construction of the office on Tuesday");
break;
case 3:
Console.WriteLine("We will start construction of the office on Wednesday");
break;
case 4:
Console.WriteLine("We will start construction of the office on Thursday");
break;
case 5:
Console.WriteLine("We will start construction of the office on Friday");
break;
case 6:
Console.WriteLine("We will start construction of the office on Saturday");
break;
case 7:
Console.WriteLine("We will start construction of the office on Sunday");
break;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
We will start construction of the office on Friday
There is another example that will further explain how to write a switch statement and how to get
the results you want.
using System.IO;
using System;
class Program1
{
static void Main()
{
int day = 7;
switch (day)
{
case 1:
Console.WriteLine("We will start construction of the office on Monday");
break;
case 2:
Console.WriteLine("We will start construction of the office on Tuesday");
break;
case 3:
Console.WriteLine("We will start construction of the office on Wednesday");
break;
case 4:
Console.WriteLine("We will start construction of the office on Thursday");
break;
case 5:
Console.WriteLine("We will start construction of the office on Friday");
break;
case 6:
Console.WriteLine("We will start construction of the office on Saturday") ;
break;
case 7:
Console.WriteLine("We will start construction of the office on Sunday");
break;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
We will start construction of the office on Sunday
Let me try an even number in the program. It will work as well as an odd number does.
using System.IO;
using System;
class Program1
{
static void Main()
{
int day = 4;
switch (day)
{
case 1:
Console.WriteLine("We will start construction of the office on Monday");
break;
case 2:
Console.WriteLine("We will start construction of the office on Tuesday");
break;
case 3:
Console.WriteLine("We will start construction of the office on Wednesday") ;
break;
case 4:
Console.WriteLine("We will start construction of the office on Thursday");
break;
case 5:
Console.WriteLine("We will start construction of the office on Friday");
break;
case 6:
Console.WriteLine("We will start construction of the office on Saturday");
break;
case 7:
Console.WriteLine("We will start construction of the office on Sunday");
break;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
We will start construction of the office on Thursday
The only thing you need to keep in mind is the number of blocks of code that you have in your
program. If you forget the number and enter something that exceeds the number of code blocks,
the result will be empty. Be careful because C# is a compiled language, which makes it hard to
spot an error or a missing line of code.
using System.IO;
using System;
class Program1
{
static void Main( )
{
int day = 9;
switch (day)
{
case 1:
Console.WriteLine("We will start construction of the office on Monday");
break;
case 2:
Console.WriteLine("We will start construction of the office on Tuesday");
break;
case 3:
Console.WriteLine("We will start construction of the office on Wednesday");
break;
case 4:
Console.WriteLine("We will start construction of the office on Thursday");
break;
case 5:
Console.WriteLine("We will start construction of the office on Friday");
break;
case 6:
Console.WriteLine("We will start construction of the office on Saturday");
break;
case 7:
Console.WriteLine("We will start construction of the office on Sunday");
break;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Loops keep executing a block of code until a specific condition has reached. Loops are really
handy because they tend to save time, cut down errors and they also make the code a lot more
readable. This chapter will walk you through the C# while loop and for loop. I will explain how
you can integrate them into your programs and how they will affect them.
C# While Loop
The while loop tends to loop through a block of code until a condition stands true. In the
following example, the code will keep running, until the condition is true. The while loop
initiates with the while keyword and it ought to include a Boolean conditional expression within
brackets that would return false or true. It also executes a code block until a specific conditional
expression returns false.
using System.IO;
using System;
class Program1
{
static void Main()
{
int x = 0; // this is the initialization
while (x < 50) // here is the condition
{
Console.WriteLine("x = {0}", x);
x++; // this is the increment
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
x=0
x=1
x=2
x=3
x=4
x=5
x=6
x=7
x=8
x=9
x = 10
x = 11
x = 12
x = 13
x = 14
x = 15
x = 16
x = 17
x = 18
x = 19
x = 20
x = 21
x = 22
x = 23
x = 24
x = 25
x = 26
x = 27
x = 28
x = 29
x = 30
x = 31
x = 32
x = 33
x = 34
x = 35
x = 36
x = 37
x = 38
x = 39
x = 40
x = 41
x = 42
x = 43
x = 44
x = 45
x = 46
x = 47
x = 48
x = 49
If we change the condition, the loop will stop at a previous or a later stage. I will set it at 25 in
the following example.
using System.IO;
using System;
class Program1
{
static void Main()
{
int x = 0; // this is the initialization
while (x < 25) // here is the condition
{
Console.WriteLine("x = {0}", x);
x++; // this is the incremen t
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
x=0
x=1
x=2
x=3
x=4
x=5
x=6
x=7
x=8
x=9
x = 10
x = 11
x = 12
x = 13
x = 14
x = 15
x = 16
x = 17
x = 18
x = 19
x = 20
x = 21
x = 22
x = 23
x = 24
If we change the operator from less than to greater than, the results will drastically change. There
will be a need to add the break keyword to stop the loop.
using System.IO;
using System;
class Program1
{
static void Main()
{
int x = 0; // this is the initialization
while (true) // here is the condition
{
Console.WriteLine("x = {0}", x);
x++; // this is the increment
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
}
}
$mcs *.cs -out:main.exe
$mono main.exe
x=0
y=1
y=2
y=3
y=4
y=5
y=6
y=7
y=8
y=9
y = 10
y = 11
y = 12
y = 13
y = 14
y = 15
y = 16
y = 17
y = 18
y = 19
y = 20
y = 21
y = 22
y = 23
y = 24
y = 25
y = 26
y = 27
y = 28
y = 29
x=1
x=2
x=3
x=4
x=5
x=6
x=7
x=8
x=9
x = 10
x = 11
x = 12
x = 13
x = 14
x = 15
x = 16
x = 17
x = 18
x = 19
x = 20
x = 21
x = 22
x = 23
x = 24
x = 25
x = 26
x = 27
x = 28
x = 29
if (x > 40)
break;
} while (x < 90);
}
}
$mcs *.cs -out:main.exe
$mono main.exe
x=0
x=1
x=2
x=3
x=4
x=5
x=6
x=7
x=8
x=9
x = 10
x = 11
x = 12
x = 13
x = 14
x = 15
x = 16
x = 17
x = 18
x = 19
x = 20
x = 21
x = 22
x = 23
x = 24
x = 25
x = 26
x = 27
x = 28
x = 29
x = 30
x = 31
x = 32
x = 33
x = 34
x = 35
x = 36
x = 37
x = 38
x = 39
x = 40
C# Nested-do-while Loop
You also can nest a do-while loop in another do-while loop. This sounds a little bit complicating
but, in practice, it is quite easier to do.
using System.IO;
using System;
class Program1
{
static void Main()
{
int x = 0;
do
{
Console.WriteLine("The value of x is as follows: {0}", x);
int y = x;
x++;
do
{
Console.WriteLine("The value of y is as follows: {0}", y);
y++;
} while (y < 30);
} while (x < 40);
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The value of x is as follows: 0
The value of y is as follows: 0
The value of y is as follows: 1
The value of y is as follows: 2
The value of y is as follows: 3
The value of y is as follows: 4
The value of y is as follows: 5
The value of y is as follows: 6
The value of y is as follows: 7
The value of y is as follows: 8
The value of y is as follows: 9
The value of y is as follows: 10
The value of y is as follows: 11
The value of y is as follows: 12
The value of y is as follows: 13
The value of y is as follows: 14
The value of y is as follows: 15
The value of y is as follows: 16
The value of y is as follows: 17
The value of y is as follows: 18
The value of y is as follows: 19
The value of y is as follows: 20
The value of y is as follows: 21
The value of y is as follows: 22
The value of y is as follows: 23
The value of y is as follows: 24
The value of y is as follows: 25
The value of y is as follows: 26
The value of y is as follows: 27
The value of y is as follows: 28
The value of y is as follows: 29
The value of x is as follows: 1
The value of y is as follows: 1
The value of y is as follows: 2
The value of y is as follows: 3
The value of y is as follows: 4
The value of y is as follows: 5
The value of y is as follows: 6
The value of y is as follows: 7
The value of y is as follows: 8
The value of y is as follows: 9
The value of y is as follows: 10
The value of y is as follows: 11
The value of y is as follows: 12
The value of y is as follows: 13
The value of y is as follows: 14
The value of y is as follows: 15
The value of y is as follows: 16
The value of y is as follows: 17
The value of y is as follows: 18
The value of y is as follows: 19
The value of y is as follows: 20
The value of y is as follows: 21
The value of y is as follows: 22
The value of y is as follows: 23
The value of y is as follows: 24
The value of y is as follows: 25
The value of y is as follows: 26
The value of y is as follows: 27
The value of y is as follows: 28
The value of y is as follows: 29
The value of x is as follows: 2
The value of y is as follows: 2
The value of y is as follows: 3
The value of y is as follows: 4
The value of y is as follows: 5
The value of y is as follows: 6
The value of y is as follows: 7
The value of y is as follows: 8
The value of y is as follows: 9
The value of y is as follows: 10
The value of y is as follows: 11
The value of y is as follows: 12
The value of y is as follows: 13
The value of y is as follows: 14
The value of y is as follows: 15
The value of y is as follows: 16
The value of y is as follows: 17
The value of y is as follows: 18
The value of y is as follows: 19
The value of y is as follows: 20
The value of y is as follows: 21
The value of y is as follows: 22
The value of y is as follows: 23
The value of y is as follows: 24
The value of y is as follows: 25
The value of y is as follows: 26
The value of y is as follows: 27
The value of y is as follows: 28
The value of y is as follows: 29
The value of x is as follows: 3
The value of y is as follows: 3
The value of y is as follows: 4
The value of y is as follows: 5
The value of y is as follows: 6
The value of y is as follows: 7
The value of y is as follows: 8
The value of y is as follows: 9
The value of y is as follows: 10
The value of y is as follows: 11
The value of y is as follows: 12
The value of y is as follows: 13
The value of y is as follows: 14
The value of y is as follows: 15
The value of y is as follows: 16
The value of y is as follows: 17
The value of y is as follows: 18
The value of y is as follows: 19
The value of y is as follows: 20
The value of y is as follows: 21
The value of y is as follows: 22
The value of y is as follows: 23
The value of y is as follows: 24
The value of y is as follows: 25
The value of y is as follows: 26
The value of y is as follows: 27
The value of y is as follows: 28
The value of y is as follows: 29
The value of x is as follows: 4
The value of y is as follows: 4
The value of y is as follows: 5
The value of y is as follows: 6
The value of y is as follows: 7
The value of y is as follows: 8
The value of y is as follows: 9
The value of y is as follows: 10
The value of y is as follows: 11
The value of y is as follows: 12
The value of y is as follows: 13
The value of y is as follows: 14
The value of y is as follows: 15
The value of y is as follows: 16
The value of y is as follows: 17
The value of y is as follows: 18
The value of y is as follows: 19
The value of y is as follows: 20
The value of y is as follows: 21
The value of y is as follows: 22
The value of y is as follows: 23
The value of y is as follows: 24
The value of y is as follows: 25
The value of y is as follows: 26
The value of y is as follows: 27
The value of y is as follows: 28
The value of y is as follows: 29
The value of x is as follows: 5
The value of y is as follows: 5
The value of y is as follows: 6
The value of y is as follows: 7
The value of y is as follows: 8
The value of y is as follows: 9
The value of y is as follows: 10
The value of y is as follows: 11
The value of y is as follows: 12
The value of y is as follows: 13
The value of y is as follows: 14
The value of y is as follows: 15
The value of y is as follows: 16
The value of y is as follows: 17
The value of y is as follows: 18
The value of y is as follows: 19
The value of y is as follows: 20
The value of y is as follows: 21
The value of y is as follows: 22
The value of y is as follows: 23
The value of y is as follows: 24
The value of y is as follows: 25
The value of y is as follows: 26
The value of y is as follows: 27
The value of y is as follows: 28
The value of y is as follows: 29
The value of x is as follows: 6
The value of y is as follows: 6
The value of y is as follows: 7
The value of y is as follows: 8
The value of y is as follows: 9
The value of y is as follows: 10
The value of y is as follows: 11
The value of y is as follows: 12
The value of y is as follows: 13
The value of y is as follows: 14
The value of y is as follows: 15
The value of y is as follows: 16
The value of y is as follows: 17
The value of y is as follows: 18
The value of y is as follows: 19
The value of y is as follows: 20
The value of y is as follows: 21
The value of y is as follows: 22
The value of y is as follows: 23
The value of y is as follows: 24
The value of y is as follows: 25
The value of y is as follows: 26
The value of y is as follows: 27
The value of y is as follows: 28
The value of y is as follows: 29
The nested do-while loop is quite interesting because of the fact that the second loop iterates
through the first one. The x integer had 7 as a value so for each number of x, the first loop
iterated around 30 times as 30 was the value of y. You can copy the code and paste it in a
compiler. Change the value of x and you will realize how it will react. If you set the value of x at
100, the first do-while loop will iterate through for each of the 100 values of x. It is amazing.
C# For Loop
When you exactly know how many times you need to loop through a certain block of code, you
should run a for loop. Usually, there are three statements in a for loop. The first statement gets
executed once before the execution of the block of code. The second statement tends to define
the condition for the execution of the block of code. The third statement gets executed after the
block of code gets executed.
using System.IO;
using System;
class Program1
{
static void Main()
{
for (int x = 50; x < 65; x++)
{
Console.WriteLine(x);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
The for loop has multiple sections that are usually separated by a semicolon. The first section is
labeled as the initializer, used to initialize a variable that acts as a local to the for loop. You
cannot access it outside of the loop. Its value can be zero or more than that. The second section
of the for loop is a Boolean expression that will be returning true or false. If a particular
expression tends to evaluate to true, it will execute the for loop. Otherwise the compiler will
execute the loop. The last section is known as an iterator. It defines the decremental or
incremental of the for loop variable. The following loop will execute a block of code 30 times.
You can increase or decrease the value to increase or decrease the number of repetitions.
using System.IO;
using System;
class Program1
{
static void Main()
{
for(int x = 0; x < 30; x++)
{
Console.WriteLine("The value of x is as follows: {0}", x);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The value of x is as follows: 0
The value of x is as follows: 1
The value of x is as follows: 2
The value of x is as follows: 3
The value of x is as follows: 4
The value of x is as follows: 5
The value of x is as follows: 6
The value of x is as follows: 7
The value of x is as follows: 8
The value of x is as follows: 9
The value of x is as follows: 10
The value of x is as follows: 11
The value of x is as follows: 12
The value of x is as follows: 13
The value of x is as follows: 14
The value of x is as follows: 15
The value of x is as follows: 16
The value of x is as follows: 17
The value of x is as follows: 18
The value of x is as follows: 19
The value of x is as follows: 20
The value of x is as follows: 21
The value of x is as follows: 22
The value of x is as follows: 23
The value of x is as follows: 24
The value of x is as follows: 25
The value of x is as follows: 26
The value of x is as follows: 27
The value of x is as follows: 28
The value of x is as follows: 29
The int x = 0 acts as an initializer. I have defined the int variable x and afterward initialized it
with 0. The second section is the expression x < 30. If the condition stands true, the compiler will
execute the block of code. When the compiler has executed it, it will move on to the 3rd section
that is known as an iterator. The x++ is considered an incremental statement that would increase
the value of x by 1. It will check and test the conditional expression at each step and then repeat
the code until the conditional expression becomes false. In the next example, I will change the
value of the initializer. The loop will execute the code at the point from where the initializer
starts. I will change its value from zero to 10.
using System.IO;
using System;
class Program1
{
static void Main()
{
for(int x = 10; x < 30; x++)
{
Console.WriteLine("The value of x is as follows: {0}", x);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The value of x is as follows: 10
The value of x is as follows: 11
The value of x is as follows: 12
The value of x is as follows: 13
The value of x is as follows: 14
The value of x is as follows: 15
The value of x is as follows: 16
The value of x is as follows: 17
The value of x is as follows: 18
The value of x is as follows: 19
The value of x is as follows: 20
The value of x is as follows: 21
The value of x is as follows: 22
The value of x is as follows: 23
The value of x is as follows: 24
The value of x is as follows: 25
The value of x is as follows: 26
The value of x is as follows: 27
The value of x is as follows: 28
The value of x is as follows: 29
However, you should make sure that the value of the initializer should not exceed the value of
the condition or the compiler will return an empty page.
using System.IO;
using System;
class Program1
{
static void Main()
{
for(int x = 40; x < 30; x++)
{
Console.WriteLine("The value of x is as follows: {0}", x);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
There are some exceptions in regard to the for loop. The initializer, the conditions, and the
iterator sections are seen as optional. You can initialize the value even outside of the for loop.
After that you can define the condition and the iterator inside the block of code. See the
following example.
using System.IO;
using System;
class Program1
{
static void Main()
{
int x = 10;
for(;;)
{
if (x < 30)
{
Console.WriteLine("The value of x is as follows: {0}", x);
x++;
}
else
break;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The value of x is as follows: 10
The value of x is as follows: 11
The value of x is as follows: 12
The value of x is as follows: 13
The value of x is as follows: 14
The value of x is as follows: 15
The value of x is as follows: 16
The value of x is as follows: 17
The value of x is as follows: 18
The value of x is as follows: 19
The value of x is as follows: 20
The value of x is as follows: 21
The value of x is as follows: 22
The value of x is as follows: 23
The value of x is as follows: 24
The value of x is as follows: 25
The value of x is as follows: 26
The value of x is as follows: 27
The value of x is as follows: 28
The value of x is as follows: 29
You can see that the results are the same. The for loop gives you the option to fill it in with any
kind of numerical data type like decimal, etc.
using System.IO;
using System;
class Program1
{
static void Main()
{
for (double d = 1.10D; d < 2.10; d+= 0.01D)
{
Console.WriteLine("The value of x: {0}", d);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The value of x: 1.1
The value of x: 1.11
The value of x: 1.12
The value of x: 1.13
The value of x: 1.14
The value of x: 1.15
The value of x: 1.16
The value of x: 1.17
The value of x: 1.18
The value of x: 1.19
The value of x: 1.2
The value of x: 1.21
The value of x: 1.22
The value of x: 1.23
The value of x: 1.24
The value of x: 1.25
The value of x: 1.26
The value of x: 1.27
The value of x: 1.28
The value of x: 1.29
The value of x: 1.3
The value of x: 1.31
The value of x: 1.32
The value of x: 1.33
The value of x: 1.34
The value of x: 1.35
The value of x: 1.36
The value of x: 1.37
The value of x: 1.38
The value of x: 1.39
The value of x: 1.4
The value of x: 1.41
The value of x: 1.42
The value of x: 1.43
The value of x: 1.44
The value of x: 1.45
The value of x: 1.46
The value of x: 1.47
The value of x: 1.48
The value of x: 1.49
The value of x: 1.5
The value of x: 1.51
The value of x: 1.52
The value of x: 1.53
The value of x: 1.54
The value of x: 1.55
The value of x: 1.56
The value of x: 1.57
The value of x: 1.58
The value of x: 1.59
The value of x: 1.6
The value of x: 1.61
The value of x: 1.62
The value of x: 1.63
The value of x: 1.64
The value of x: 1.65
The value of x: 1.66
The value of x: 1.67
The value of x: 1.68
The value of x: 1.69
The value of x: 1.7
The value of x: 1.71
The value of x: 1.72
The value of x: 1.73
The value of x: 1.74
The value of x: 1.75
The value of x: 1.76
The value of x: 1.77
The value of x: 1.78
The value of x: 1.79
The value of x: 1.8
The value of x: 1.81
The value of x: 1.82
The value of x: 1.83
The value of x: 1.84
The value of x: 1.85
The value of x: 1.86
The value of x: 1.87
The value of x: 1.88
The value of x: 1.89
The value of x: 1.9
The value of x: 1.91
The value of x: 1.92
The value of x: 1.93
The value of x: 1.94
The value of x: 1.95
The value of x: 1.96
The value of x: 1.97
The value of x: 1.98
The value of x: 1.99
The value of x: 2
The value of x: 2.01
The value of x: 2.02
The value of x: 2.03
The value of x: 2.04
The value of x: 2.05
The value of x: 2.06
The value of x: 2.07
The value of x: 2.08
The value of x: 2.09
The value of x: 2.1
Up until now you have seen how you can increment the value in the code with a for loop. You
also have the option to decrease the value of the variable by using the following code.
using System.IO;
using System;
class Program1
{
static void Main()
{
for(int x = 10; x > 0; x--)
{
Console.WriteLine("The value of x is: {0}", x);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The value of x is: 10
The value of x is: 9
The value of x is: 8
The value of x is: 7
The value of x is: 6
The value of x is: 5
The value of x is: 4
The value of x is: 3
The value of x is: 2
The value of x is: 1
You also can push the figure into negatives by setting conditions that way. This can be handy
when you move on to building programs in C#. Some programs demand negative numbers,
calculated by a loop.
using System.IO;
using System;
class Program1
{
static void Main()
{
for(int x = 10; x > -10; x--)
{
Console.WriteLine("The value of x is: {0}", x);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The value of x is: 10
The value of x is: 9
The value of x is: 8
The value of x is: 7
The value of x is: 6
The value of x is: 5
The value of x is: 4
The value of x is: 3
The value of x is: 2
The value of x is: 1
The value of x is: 0
The value of x is: -1
The value of x is: -2
The value of x is: -3
The value of x is: -4
The value of x is: -5
The value of x is: -6
The value of x is: -7
The value of x is: -8
The value of x is: -9
Even if you have a condition, set at the higher number, you can exit the loop at will by using the
break keyword. I will take a previous example and enter in it the break keyword to see how it
stops the loop and allows you to exit the loop at will.
using System.IO;
using System;
class Program1
{
static void Main()
{
for (int x = 0; x < 14; x++)
{
if( x == 7 )
break;
Console.WriteLine("The Value of x is: {0}", x);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
The value of x is: 0
The value of x is: 1
The value of x is: 2
The value of x is: 3
The value of x is: 4
The value of x is: 5
The value of x is: 6
Even though the condition was set to loop through the block of code until it reached the figure
14, the loop stopped at 7.
Multiple Expressions
A for loop will also include multiple iterators and initializer statements that are usually separated
by a comma, as is shown below.
using System.IO;
using System;
class Program1
{
static void Main()
{
for (int x = 0, y = 0; x+y < 15; x++, y++)
{
Console.WriteLine("Value of x: {0}, Value of y: {1} ", x,y);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Value of x: 0, Value of y: 0
Value of x: 1, Value of y: 1
Value of x: 2, Value of y: 2
Value of x: 3, Value of y: 3
Value of x: 4, Value of y: 4
Value of x: 5, Value of y: 5
Value of x: 6, Value of y: 6
Value of x: 7, Value of y: 7
You also can add an iterator and an initializer in the for loop. This is a more complex but smart
form of writing a for loop in C#.
using System.IO;
using System;
class Program
{
static void Main()
{
int x = 0, y = 10;
for (Console.WriteLine($"Initializer: x={x}, y={y}");
x++ < y--;
Console.WriteLine($"Iterator: x={x}, y={y}"))
{
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Initializer: x=0, y=10
Iterator: x=1, y=9
Iterator: x=2, y=8
Iterator: x=3, y=7
Iterator: x=4, y=6
Iterator: x=5, y=5
Programmers should be able to break big programs into smaller ones that are easier to handle.
The program should be short enough so that it can be easily readable. You can divide the class
code into little chunks that are labeled as methods. These are properly designed methods that can
simplify the job of writing complex programs. A method is just like a function that you might
have learned about in other programming languages. The only difference is that a method is part
of a C# class.
Methods are statements that allow a programmer to reuse an already written block of code. It
saves excessive use of memory and eases off the coding process. Methods also increase the
readability of code. In simple words, a method is also known as a collection of statements that
perform particular tasks and likewise return the results. There may come certain methods along
your way which don’t return anything.
Defining Methods
A method is generally defined with a name that is followed by a parenthesis. There also are some
predefined methods in C# such as the Main() which you have been acquainted with right from
the start of the book.
using System.IO;
using System;
class Program1
{
static void ThisMethod()
{
Console.WriteLine("Let's execute it!");
}
static void Main(string[] args)
{
ThisMethod();
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Let's execute it!
I have created a method, assign it a string value, and then called it in the end. In the above block
of code, the keyword static means that this method belongs to the Program1 class. The keyword
void means that the method doesn’t have a return value. You can call a method as many times as
you need to.
using System.IO;
using System;
class Program1
{
static void ThisMethod()
{
Console.WriteLine("Let's execute it!");
}
static void Main(string[] args)
{
ThisMethod();
ThisMethod();
ThisMethod();
ThisMethod();
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Let's execute it!
Let's execute it!
Let's execute it!
Let's execute it!
Parameters
You can pass on information to a method by using parameters. These parameters tend to act as
variables within the method. They are specified after the name of the method inside of the
parameters. Add many parameters as you want in your program. Separate them with a comma.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static void ThisMethod(string fname)
{
Console.WriteLine(fname + " will come to the class after playing football");
}
static void Main(string[] args)
{
ThisMethod("Jack");
ThisMethod("Tom");
ThisMethod("Fin");
ThisMethod("Jasmine");
ThisMethod("Sylvia");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Jack will come to the class after playing football
Tom will come to the class after playing football
Fin will come to the class after playing football
Jasmine will come to the class after playing football
Sylvia will come to the class after playing football
You also can add default parameters to the methods so that if you left them empty, it is filled by
the default parameters.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static void ThisMethod(string fname = " Donald will come to the class after playing
football")
{
Console.WriteLine(fname);
}
static void Main(string[] args)
{
ThisMethod();
ThisMethod();
ThisMethod();
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Donald will come to the class after playing football
Donald will come to the class after playing football
Donald will come to the class after playing football
Multiple Parameters
You can pass on more than one parameter to the method if you are building a complex program.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static void ThisMethod(string fname, int yearofbirth)
{
Console.WriteLine(fname + " was born in " + yearofbirth);
}
static void Main(string[] args)
{
ThisMethod("Jack", 2000);
ThisMethod("Tom", 1998);
ThisMethod("Sylvia", 1995);
ThisMethod("Yik", 1992);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Jack was born in 2000
Tom was born in 1998
Sylvia was born in 1995
Yik was born in 1992
Return Values
You can use the void keyword if you want the method to return a value. This technique can be
used in programs that involve mathematical calculations. See the following examples.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y)
{
return 10 + y;
}
static void Main(string[] args)
{
Console.WriteLine(ThisMethod(3));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
13
I will now change the values and use a different mathematical operator to see the result.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y)
{
return 15 - y;
}
static void Main(string[] args)
{
Console.WriteLine(ThisMethod(50));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
-35
You can use the operator for the multiplication of two digits.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y)
{
return 15 * y;
}
static void Main(string[] args)
{
Console.WriteLine(ThisMethod(50));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
750
This last operator for the division.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y)
{
return 15 / y;
}
static void Main(string[] args)
{
Console.WriteLine(ThisMethod(50));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
0
Two Parameters
Now I will be using two parameters in the same method.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y, int z)
{
return y + z;
}
static void Main(string[] args)
{
Console.WriteLine(ThisMethod(5, 6));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
11
I will add more console statements to apply the method to different parameters.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y, int z)
{
return y - z;
}
static void Main(string[] args)
{
Console.WriteLine(ThisMethod(15, 6));
Console.WriteLine(ThisMethod(355, 6));
Console.WriteLine(ThisMethod(35, 6));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
9
349
29
You can apply different mathematical operators to get the desired results. See the
following block of code.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y, int z)
{
return y * z;
}
static void Main(string[] args)
{
Console.WriteLine(ThisMethod(15, 6));
Console.WriteLine(ThisMethod(355, 6));
Console.WriteLine(ThisMethod(35, 6));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
90
2130
210
Here comes division.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y, int z)
{
return y / z;
}
static void Main(string[] args)
{
Console.WriteLine(ThisMethod(15, 6));
Console.WriteLine(ThisMethod(355, 6));
Console.WriteLine(ThisMethod(35, 6));
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
2
59
5
Store Result
You have the option to store the result in a variable. Suppose you are creating a program in
which you invite users to fill in their input which you can view later on. You can direct the input
to a variable so that it would be easier to access whenever you need to view it.
using System.IO;
using System;
namespace MyApp
{
class Program1
{
static int ThisMethod(int y, int z)
{
return y / z;
}
static void Main(string[] args)
{
This chapter will walk you through the ins and outs of object-oriented programming. C# supports
object-oriented programming. A class in C# is a bundle of data and functions that belong
together into a single tidy package. C# gives you the freedom to create classes and build
programs. These are basic concepts of OOP. You can model real-life objects on classes. A class
is like a user-defined blueprint from which you can create objects. A class, generally, combines
methods and fields into a single unit. Classes in C# support polymorphism.
A class contains a single keyword namely class, followed by an identifier, and each class may
have many different attributes. An object is a basic unit of object-oriented programming, and
may reflect any real-life entity. You can create many objects through C# programs. Many objects
tend to interact by invoking different methods. A particular object consists of a state which is
represented by different attributes of a particular object. It also reflects the properties of the
object. Another feature of the object is its behavior which is represented by different methods of
a particular object. It also reflects how an object responds. The third feature of a class is identity,
which gives a unique name to a particular object, and also enables it to interact with different
other objects present in the same class.
For example, a cat is an object. It rolls on the ground, sits and jumps. When we create an object
in a class, the class will be instantiated. All the different instances tend to share different
attributes and behavior of a class. There may be more than one instance in a class.
Creating C# Class
I will be using a new operator to initialize an object in a class.
using System;
// Declaration of class
public class Cat {
// Instance Variables
String cname;
String cbreed;
int cage;
String ccolor;
// This is Property 1
public String getName()
{
return cname;
}
// This is Property 2
public String getBreed()
{
return cbreed;
}
// This is Property 3
public int getAge()
{
return cage;
}
// This is Property 4
public String getColor()
{
return ccolor;
}
// Method 1
public String toString( )
{
return ("Hi this is " + this.getName()
+ ".\nYou will be pleased to know that my breed, age and color are " +
this.getBreed()
+ ", " + this.getAge() + ", " + this.getColor());
}
// Declaration of class
public class Cat {
// Instance Variables
String cname ;
String cbreed;
int cage;
String ccolor;
// This is Property 1
public String getName()
{
return cname;
}
// This is Property 2
public String getBreed()
{
return cbreed;
}
// This is Property 3
public int getAge()
{
return cage;
}
// This is Property 4
public String getColor()
{
return ccolor;
}
// Method 1
public String toString()
{
return ("Hi this is " + this.getName()
+ ".\nYou will be pleased to know that my breed, age and color are as
followed : " + this.getBreed()
+ ", " + this.getAge() + ", " + this.getColor());
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Hi this is Timmy.
You will be pleased to know that my breed, age and color are as followed : ragdoll, 6, black.
Hi this is Tim.
You will be pleased to know that my breed, age and color are as followed : ragdoll, 9, white.
Hi this is Hitman.
You will be pleased to know that my breed, age and color are as followed : Savannah, 9, brown.
Hi this is Beamer.
You will be pleased to know that my breed, age and color are as followed : sphynx, 8, white.
You can see that I have created four different objects through the process of instantiation. You
can add as many instances to the cat class as you like. This class has a single constructor.
// Declaration of class
public class Car {
// Instance Variables
String cname;
String cmodel;
int cmake;
String ccolor;
// This is Property 1
public String getName()
{
return cname;
}
// This is Property 2
public String getModel()
{
return cmodel;
}
// This is Property 3
public int getMake()
{
return cmake;
}
// This is Property 4
public String getColor()
{
return ccolor;
}
// Method 1
public String toString()
{
return ("This car is " + this.getName()
+ ".\nIts model, year and color are as followed respectively : " +
this.getModel()
+ ", " + this.getMake() + ", " + this.getColor());
}
}
$mcs *.cs -out:main.exe
$mono main.exe
This car is BMW.
Its model, year and color are as followed respectively : X1, 2008, black.
Now I will add three more cars to the same class. You don’t have to change anything in the class.
All you are required to do is make the necessary changes in the instances that I have added. Fill it
in with the details by which you want to create more objects.
using System;
// Declaration of class
public class Car {
// Instance Variables
String cname;
String cmodel;
int cmake;
String ccolor;
// This is Property 1
public String getName()
{
return cname;
}
// This is Property 2
public String getModel()
{
return cmodel;
}
// This is Property 3
public int getMake()
{
return cmake;
}
// This is Property 4
public String getColor()
{
return ccolor;
}
// Method 1
public String toString()
{
return ("This car is known as " + this.getName()
+ ".\nIts model, year and color are as followed respectively : " +
this.getModel()
+ ", " + this.getMake() + ", " + this.getColor());
}
}
$mcs *.cs -out:main.exe
$mono main.exe
This car is known as BMW.
Its model, year and color are as followed respectively : X1, 2008, black.
This car is known as Range Rover.
Its model, year and color are as followed respectively : Velar, 2016, black.
This car is known as Audi.
Its model, year and color are as followed respectively : A4 Sedan, 2014, black.
This car is known as Mercedes.
Its model, year and color are as followed respectively : C-Class, 2019, white.
Class Members
In the following I will once again create a car class which will have two fields, one for the color
and the other for the speed.
using System;
namespace MyApp
{
class Cars
{
string ccolor = "white";
int cmaxSpeed = 150;
static void Main(string[] args)
{
Cars myObject = new Cars();
Console.WriteLine(myObject.ccolor);
Console.WriteLine(myObject.cmaxSpeed);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
white
150
If you want to let your users fill in the fields of the objects, you can fill them later on while you
are creating class objects.
using System;
namespace MyApp
{
class Cars
{
string ccolor ;
int cmaxSpeed ;
static void Main(string[] args)
{
Cars myObject = new Cars();
myObject.ccolor = "white";
myObject.cmaxSpeed = 150;
Console.WriteLine(myObject.ccolor);
Console.WriteLine(myObject.cmaxSpeed);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
white
150
I am now going to add two more fields to the same class to show how easy it is to add fields to a
single class.
using System;
namespace MyApp
{
class Cars
{
string ccolor ;
int cmaxSpeed ;
int cmake ;
string cmodel;
static void Main (string[] args)
{
Cars myObject = new Cars();
myObject.ccolor = "white";
myObject.cmaxSpeed = 150;
myObject.cmake = 2002;
myObject.cmodel = "BMW";
Console.WriteLine (myObject.ccolor) ;
Console.WriteLine (myObject.cmaxSpeed) ;
Console.WriteLine (myObject.cmake) ;
Console.WriteLine (myObject.cmodel) ;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
white
150
2002
BMW
You have already learned about how you can add different objects to a single class. There is
another method that you can use to create objects.
using System;
namespace MyApp
{
class Cars
{
string ccolor ;
int cmaxSpeed ;
int cmake ;
string cmodel;
static void Main (string[] args)
{
Cars BMW = new Cars();
BMW.ccolor = "Black" ;
BMW.cmaxSpeed = 200 ;
BMW.cmake = 2015 ;
BMW.cmodel = "Turismo" ;
Console.WriteLine (BMW.ccolor) ;
Console.WriteLine (BMW.cmaxSpeed) ;
Console.WriteLine (BMW.cmake) ;
Console.WriteLine (BMW.cmodel) ;
Console.WriteLine (Audi.ccolor) ;
Console.WriteLine (Audi.cmaxSpeed) ;
Console.WriteLine (Audi.cmake) ;
Console.WriteLine (Audi.cmodel) ;
Console.WriteLine (Mercedes.ccolor) ;
Console.WriteLine (Mercedes.cmaxSpeed) ;
Console.WriteLine (Mercedes.cmake) ;
Console.WriteLine (Mercedes.cmodel) ;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Black
200
2015
Turismo
Black
250
2019
A4
Silver
100
2013
C-Class
Class Methods
Methods are inherent to classes and they are used to define how an object inside of a class
behaves. Just like the fields, you have the power to access different methods by using the dot
syntax. You must note that methods should be public. You must remember that you use the
method name along with the pair of parentheses and a semicolon. I will add a method to the cars
class mentioned above.
using System;
namespace MyApp
{
class Cars
{
string ccolor ;
int cmaxSpeed ;
int cmake ;
string cmodel;
myObj.fullThrot();
Console.WriteLine (BMW.ccolor) ;
Console.WriteLine (BMW.cmaxSpeed) ;
Console.WriteLine (BMW.cmake) ;
Console.WriteLine (BMW.cmodel) ;
Console.WriteLine (Audi.ccolor) ;
Console.WriteLine (Audi.cmaxSpeed) ;
Console.WriteLine (Audi.cmake) ;
Console.WriteLine (Audi.cmodel) ;
Console.WriteLine (Mercedes.ccolor) ;
Console.WriteLine (Mercedes.cmaxSpeed) ;
Console.WriteLine (Mercedes.cmake) ;
Console.WriteLine (Mercedes.cmodel) ;
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
These cars go from zero to a hundred in five seconds!
Black
210
2013
A4
Black
250
2019
A4
Silver
100
2013
C-Class
In the above example, the method was applied to all the instances that I had created. You can add
more instances to the class and also create and add more methods as well to experiment how far
you can go with the programming. It would really be fun and interesting.
You can create multiple classes to organize the program in a better and efficient way. For
example, you can create a separate class for field methods and another one for the execution.
C# Class Constructor
This is a special method that you can use to initialize objects. Its advantage is that it can be called
when a class object is created. You can use it to settle down the initial values for different fields.
using System;
namespace MyApp
{
// this will create a Car class
class Cars
{
public string cmodel; // This will create a field
// I will now Create the class constructor for the above-mentioned Cars class
public Cars( )
{
cmodel = "C-classic"; // This will set initial value for the model
}
static void Main(string[] args)
{
Cars Ford = new Cars();
Console.WriteLine(Ford.cmodel);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
C-classic
Try it with another model.
using System;
namespace MyApp
{
// this will create a Car class
class Cars
{
public string cmodel; // This will create a field
public string ccolor;
public int cmake;
// I will now Create the class constructor for the above mentioned Cars class
public Cars()
{
cmodel = "C-classic"; // This will set initial value for the model
ccolor = "White";
cmake = 2002 ;
}
static void Main(string[] args)
{
Cars Ford = new Cars();
Console.WriteLine(Ford.cmodel);
Console.WriteLine(Ford.ccolor);
Console.WriteLine(Ford.cmake);
Multiple Parameters
You can add to the class as many parameters as you want to.
using System;
namespace MyApp
{
// this will create a Car class
class Cars
{
public string cmodel; // This will create a field
public string ccolor;
public int cmake;
// I will now Create the class constructor for the above mentioned Cars clas s
public Cars(string modelName, string modelColor, int modelMake)
{
cmodel = modelName ; // This will set initial value for the model
ccolor = modelColor ;
cmake = modelMake ;
}
static void Main(string[] args)
{
Cars Ford = new Cars("Mustang", "White", 2009);
Console.WriteLine(Ford.ccolor + " " + Ford.cmake + " " + Ford.cmodel);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
White 2009 Mustang
White 2009 BMW
Black 2010 Mercedes
Black 2015 Rangerover
C# Properties
Combined with the properties is the concept of encapsulation. Encapsulation means that sensitive
data ought to be hidden from outside users. You can do this by declaring variables and fields as
private. You also can do that by providing public, set and get methods through properties to
update and access the value of a particular private field.
You only can access private variables inside the same class. No outside class can access it.
However, it can be done through properties. A property can be defined as a combination of a
method and a variable. There generally are two methods of property; one is the get and the other
is the set method.
using System;
namespace MyApp
{
class Cars
{
private string cname; // field
public string cName // property
{
get { return cname; }
set { cname = value; }
}
}
class Program1
{
static void Main(string[] args)
{
Cars thisObj = new Cars();
thisObj.cName = "BMW";
Console.WriteLine(thisObj.cName);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
BMW
We can change the object in the class with the same properties. See the following example.
using System;
namespace MyApp
{
class Cars
{
private string cname; // field
public string cName // property
{
get { return cname; }
set { cname = value; }
}
}
class Program1
{
static void Main(string[] args)
{
Cars thisObj = new Cars();
thisObj.cName = "Mercedes";
Console.WriteLine(thisObj.cName);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Mercedes
There is another way to write properties in a class. C# offers shorthand to automatically write
properties if you don’t want to define the field for the property. All you are required to write is
set; and get; within the scope of the property. In the following example, I will write the
properties automatically through shorthand. The difference between the two methods is that you
have to write less code that way.
using System;
namespace MyApp
{
class Cars
{
public string cName // property
{ get; set; }
}
class Program1
{
static void Main(string[] args)
{
Cars thisObj = new Cars();
thisObj.cName = "Mercedes";
Console.WriteLine(thisObj.cName);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Mercedes
Chapter Eight
C# Classes Explained Further
In C# you can inherit methods and fields from one class to another one. The concept of
inheritance concept is generally divided into two categories. One is named the Base Class which
is the class from which the other class is inherited. The other one is the Derived Class which
inherits properties from the parent class. To start the process of inheritance, you can use the :
symbol. In the following example, I will create one parent and one child class to show how you
can use them in real programming.
using System;
namespace MyApp
{
class Cars // base class (the parent class)
{
public string company = "Ford"; // The Cars field
public void honk() // The Cars method
{
Console.WriteLine("This is a brand new: ");
}
}
class MyCar : Cars // derived class (child)
{
public string cmodelName = "Mustang"; // Car field
}
class Program1
{
static void Main(string[] args)
{
// Create a myCar object
MyCar myCar = new MyCar();
myCar.honk();
Console.WriteLine(myCar.company + " " + myCar.cmodelName);
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
This is a brand new:
Ford Mustang
You can see that the parent class in the code is named as Cars while the child class in the code is
named as MyCar. Inheritance is considered an important aspect of Object-oriented Programming
(OOP). It is a particular mechanism in C# by which the child class is allowed to inherit different
features of the parent class. The parent class, whose features are inherited by the child class is
also known as the superclass or the base class. The child class which inherits the features of the
parent class is dubbed as a subclass or derived class or extended class. The subclass also can add
its own methods and fields besides inheriting methods and fields of the superclass.
The inheritance feature of C# classes tends to support the concept of reusability. When you
intend to create a new class and there already exists one which includes some code that you
want, you can derive a new class from an existing one. Take a look at another example of an
inherited class.
using System;
namespace MyApp {
class Program1 {
// data members
public string cname;
public string csubject;
// Driver class
class Sudo1 {
// Main Method
static void Main(string[] args)
{
g.creaders("Tom", "Physics");
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
This is the child class or inherited class
My name is Tom
My most favorite subject is as follows: Physics
Polymorphism
The term polymorphism literally means “having multiple forms.”. If you have read chemistry,
you might have been acquainted with the term polymorphism. It occurs when many classes are
generally related to each other by the method of inheritance. Inheritance allows programmers to
inherit methods and fields from another class. Polymorphism makes use of the methods to
perform many tasks. This will allow them to perform one action in several ways.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
}
}
}
$mono main.exe
Our animal is making a sound at the moment
Our animal is making a sound at the moment
Our animal is making a sound at the moment
I am adding one more animal to the code.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mono main.exe
Our animal is making a sound at the moment
Our animal is making a sound at the moment
Our animal is making a sound at the moment
Our animal is making a sound at the moment
The output is not what you might be expecting. There is no mention of the type of sounds that
the animals had been producing. The base class method has overridden the derived class method
because they share the same name. You can add the virtual keyword to the method.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public virtual void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public override void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public override void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public override void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
$mono main.exe
Our animal is making a sound at the moment
The cat says: Meow Meow
The horse says: Neigh Neigh
The dog says: Bau Bau
Abstraction
Data abstraction is known as the process of hiding specific details and also showing the essential
information to the user. You can achieve abstraction with interfaces or abstract classes. You can
use the abstract keyword for methods and classes. An abstract class is a kind of restricted class
that cannot be used for the creation of an object. The abstract method can be used in the abstract
class. It lacks a body.
using System;
namespace MyApp
{
abstract class Animalkingdom // This is the Base class also known as the parent class
{
public abstract void theanimalSound();
public void csleep()
{
Console.WriteLine("Zzz");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public override void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public override void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public override void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Interfaces
This is yet another method to achieve abstraction. Note the changes in the code.
using System;
namespace MyApp
{
interface IAnimalkingdom // This is the Base class also known as the parent class
{
void theanimalSound();
}
class Cat : IAnimalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : IAnimalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : IAnimalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Error Messages
Classes are complex and lengthy which raises the stakes of committing blunders. If you miss a
curly brace or add an extra to the code, your program will return an error. As C# is a compiled
language, it gets pretty much tough to spot the error. Therefore you need to write it cleanly so
that if an error pops up, you can detect it and correct it. See the following error.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animakingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 2 error(s), 3 warnings
main.cs(15,15): warning CS0108: `MyApp.Cat.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(23,15): warning CS0108: `MyApp.Horse.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(31,15): warning CS0108: `MyApp.Dog.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(44,5): error CS0246: The type or namespace name `Animakingdom' could not be
found. Are you missing an assembly reference?
main.cs(49,5): error CS0841: A local variable `thisDog' cannot be used before it is
declared
I couldn’t add a single l to the word animal and the entire program is ruined with no hint of the
error. You have to scan the entire code and spot the error. See another misspelling error in the
following example.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.riteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 1 error(s), 3 warnings
main.cs(15,15): warning CS0108: `MyApp.Cat.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(23,15): warning CS0108: `MyApp.Horse.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(31,15): warning CS0108: `MyApp.Dog.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(25,13): error CS0117: `System.Console' does not contain a definition for
`riteLine'
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
In the above error, I skipped a w in WriteLine. Can you understand the error message? Not at the
first look. But you can do that if you read the message twice or thrice. See what happens if the
names you used as variables don’t match. This one is more self-evident than the previous errors.
You may find it easier to detect them. However, you should read the error message and trying to
decipher its meaning. In this way, if something similar pops up on your screen during
programming, you will find it easier and quicker to fix. I will change the names of variables so
they don’t match.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
MyCat.theanimalSound();
MyHorse.theanimalSound();
MyDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 3 error(s), 3 warnings
main.cs(15,15): warning CS0108: `MyApp.Cat.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(23,15): warning CS0108: `MyApp.Horse.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(31,15): warning CS0108: `MyApp.Dog.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(47,5): error CS0103: The name `MyCat' does not exist in the current context
main.cs(48,5): error CS0103: The name `MyHorse' does not exist in the current context
main.cs(49,5): error CS0103: The name `MyDog' does not exist in the current context
A common error that you may confront while you are creating a program is caused by missing
any curly braces. See the following code.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
$mcs *.cs -out:main.exe
Compilation failed: 1 error(s), 0 warnings
main.cs(51,246): error CS1525: Unexpected symbol `end-of-file'
This error message clearly tells you that there is an unexpected symbol at the end of the file.
Now see the following error.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound( )
{
Console.WriteLine("The cat says: Meow Meow");
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound() ;
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 6 error(s), 0 warnings
main.cs(20,0): error CS1525: Unexpected symbol `class'
main.cs(21,0): error CS1525: Unexpected symbol `{'
main.cs(22,2): error CS1525: Unexpected symbol `public'
main.cs(22,10): error CS1547: Keyword `void' cannot be used in this context
main.cs(22,28): error CS1525: Unexpected symbol `('
main.cs(52,246): error CS1525: Unexpected symbol `end-of-file'
This one is a bit confusing because everything is alright at the end of the file. However, there are
a couple of wrong symbols in the file. You need to spot them and fill the vacant spot with the
correct symbols. See the following error and spot what is missing in the program.
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 4 error(s), 3 warnings
main.cs(15,15): warning CS0108: `MyApp.Cat.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(23,15): warning CS0108: `MyApp.Horse.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(31,15): warning CS0108: `MyApp.Dog.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(9,5): error CS0103: The name `Console' does not exist in the current context
main.cs(17,5): error CS0103: The name `Console' does not exist in the current context
main.cs(25,5): error CS0103: The name `Console' does not exist in the current context
main.cs(33,5): error CS0103: The name `Console' does not exist in the current context
A hint is that something is missing at the top of the file. This happens more often when you are
copying code from one file to another. If you see the error on the screen that the compiler has
found an unexpected symbol in the program, you should know that you might have missed a
semicolon or a curly brace. The following error message does tell you that a semicolon is either
missing or is in excess, but it doesn’t tell where the error lies. Just like other errors, you have to
find it yourself. Take a look and try to find the error.
using System
namespace MyApp
{
class Animalkingdom; // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound( )
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 7 error(s), 0 warnings
main.cs(3,0): error CS1525: Unexpected symbol `namespace', expecting `.', `::', `;', `<', or
`='
main.cs(5,19): error CS1525: Unexpected symbol `;', expecting `(', `:', `{', or `where'
main.cs(7,9): error CS1525: Unexpected symbol `void', expecting `(', `:', `{', or `where'
main.cs(9,4): error CS1525: Unexpected symbol `Console', expecting `(', `:', `{', or
`where'
main.cs(9,21): error CS1525: Unexpected symbol `(', expecting `(', `:', `{', or `where'
main.cs(10,3): error CS1514: Unexpected symbol `}', expecting `.' or `{'
main.cs(52,0): error CS1525: Unexpected symbol `}'
So I added an extra semicolon to the program; the compiler returned this in the form of an error.
Now in the next example, I will remove a couple of semicolons. See the error message and try to
familiarize yourself with this error message so that you may fix this kind of problem head-on
while you are writing a program.
using System
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment")
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow")
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh" )
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 4 error(s), 0 warnings
main.cs(3,0): error CS1525: Unexpected symbol `namespace', expecting `.', `::', `;', `<', or
`='
main.cs(10,3): error CS1002: ; expected
main.cs(18,3): error CS1002: ; expected
main.cs(26,3): error CS1002: ; expected
Another common mistake that programmers make is that they miss out on writing the right upper
case and lower case letters. In the following error message, I will deliberately miss out on using
capital letters where I must use them. See the error message and familiarize yourself with it to fix
it if the same pops up while you are writing a program. See the following example.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new cat(); // Creating a Pig object
Animalkingdom thisHorse = new horse(); // Creating a Dog object
Animalkingdom thisDog = new dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 3 error(s), 3 warnings
main.cs(15,15): warning CS0108: `MyApp.Cat.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(23,15): warning CS0108: `MyApp.Horse.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(31,15): warning CS0108: `MyApp.Dog.theanimalSound()' hides inherited
member `MyApp.Animalkingdom.theanimalSound()'. Use the new keyword if hiding
was intended
main.cs(7,15): (Location of the symbol related to previous warning)
main.cs(42,33): error CS0246: The type or namespace name `cat' could not be found. Are
you missing an assembly reference?
main.cs(43,35): error CS0246: The type or namespace name `horse' could not be found.
Are you missing an assembly reference?
main.cs(44,33): error CS0246: The type or namespace name `dog' could not be found.
Are you missing an assembly reference?
The next error is a simple one; that’s why you should decipher the error message yourself and try
to spot it.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound
{
Console.WriteLine("Our animal is making a sound at the moment");
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound
{
Console.WriteLine("The cat says: Meow Meow");
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound
{
Console.WriteLine("The horse says: Neigh Neigh");
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound
{
Console.WriteLine("The dog says: Bau Bau");
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat; // Creating a Pig object
Animalkingdom thisHorse = new Horse; // Creating a Dog object
Animalkingdom thisDog = new Dog;
thisAnimal.theanimalSound ;
thisCat.theanimalSound;
thisHorse.theanimalSound;
thisDog.theanimalSound;
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 11 error(s), 0 warnings
main.cs(7,10): error CS0547: `MyApp.Animalkingdom.theanimalSound': property or
indexer cannot have void type
main.cs(9,5): error CS1014: A get or set accessor expected
main.cs(15,10): error CS0547: `MyApp.Cat.theanimalSound': property or indexer cannot
have void type
main.cs(17,5): error CS1014: A get or set accessor expected
main.cs(23,10): error CS0547: `MyApp.Horse.theanimalSound': property or indexer
cannot have void type
main.cs(25,5): error CS1014: A get or set accessor expected
main.cs(31,10): error CS0547: `MyApp.Dog.theanimalSound': property or indexer
cannot have void type
main.cs(33,5): error CS1014: A get or set accessor expected
main.cs(42,35): error CS1525: Unexpected symbol `;', expecting `(', `[', or `{'
main.cs(43,39): error CS1525: Unexpected symbol `;', expecting `(', `[', or `{'
main.cs(44,35): error CS1525: Unexpected symbol `;', expecting `(', `[', or `{'
I will explain in this error the absence of the inverted commas. Sometimes they are too much that
you lose track of them while writing a program. See the following error message and try to
understand it so that you may fix it in the future.
using System;
namespace MyApp
{
class Animalkingdom // This is the Base class also known as the parent class
{
public void theanimalSound()
{
Console.WriteLine("Our animal is making a sound at the moment);
}
}
class Cat : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The cat says: Meow Meow');
}
}
class Horse : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The horse says: Neigh Neigh);
}
}
class Dog : Animalkingdom // This is the derived class (child)
{
public void theanimalSound()
{
Console.WriteLine("The dog says: Bau Bau);
}
}
class Program1
{
static void Main(string[] args)
{
Animalkingdom thisAnimal = new Animalkingdom(); // Creating an Animal object
Animalkingdom thisCat = new Cat(); // Creating a Pig object
Animalkingdom thisHorse = new Horse(); // Creating a Dog object
Animalkingdom thisDog = new Dog();
thisAnimal.theanimalSound();
thisCat.theanimalSound();
thisHorse.theanimalSound();
thisDog.theanimalSound();
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 12 error(s), 0 warnings
main.cs(9,67): error CS1010: Newline in constant
main.cs(10,2): error CS1525: Unexpected symbol `}', expecting `)' or `,'
main.cs(10,3): error CS1002: ; expected
main.cs(17,49): error CS1010: Newline in constant
main.cs(18,2): error CS1525: Unexpected symbol `}', expecting `)' or `,'
main.cs(18,3): error CS1002: ; expected
main.cs(25,52): error CS1010: Newline in constant
main.cs(26,2): error CS1525: Unexpected symbol `}', expecting `)' or `,'
main.cs(26,3): error CS1002: ; expected
main.cs(33,46): error CS1010: Newline in constant
main.cs(34,2): error CS1525: Unexpected symbol `}', expecting `)' or `,'
main.cs(34,3): error CS1002: ; expected
In the following error code, I will use the switch statement to see which kind of errors you may
experience. I will change the case of keywords like a switch in the program. See the following
example.
using System.IO;
using System;
class Program
{
static void Main()
{
Int day = 1;
Switch (day)
{
Case 1:
Console.WriteLine("We will start construction of the office on Monday");
break;
Case 2:
Console.WriteLine("We will start construction of the office on Tuesday");
break;
Case 3:
Console.WriteLine("We will start construction of the office on Wednesday");
break;
case 4:
Console.WriteLine("We will start construction of the office on Thursday");
break;
case 5:
Console.WriteLine("We will start construction of the office on Friday");
break ;
case 6:
Console.WriteLine("We will start construction of the office on Saturday");
break;
case 7:
Console.WriteLine("We will start construction of the office on Sunday");
break;
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 15 error(s), 0 warnings
main.cs(10,0): error CS1525: Unexpected symbol `{'
main.cs(11,7): error CS1525: Unexpected symbol `1'
main.cs(11,8): error CS1525: Unexpected symbol `:'
main.cs(14,7): error CS1525: Unexpected symbol `2'
main.cs(14,8): error CS1525: Unexpected symbol `:'
main.cs(17,7): error CS1525: Unexpected symbol `3'
main.cs(17,8): error CS1525: Unexpected symbol `:'
main.cs(20,2): error CS1525: Unexpected symbol `case'
main.cs(20,8): error CS1525: Unexpected symbol `:'
main.cs(23,2): error CS1525: Unexpected symbol `case'
main.cs(23,8): error CS1525: Unexpected symbol `:'
main.cs(26,2): error CS1525: Unexpected symbol `case'
main.cs(26,8): error CS1525: Unexpected symbol `:'
main.cs(29,2): error CS1525: Unexpected symbol `case'
main.cs(29,8): error CS1525: Unexpected symbol `:'
In the following code sample, you will see what happens if you misspell the keywords in a
program.
using System.IO;
using System;
class Program1
{
stati vid Main()
{
int day = 1;
switch (day)
{
case 1:
Consle.WriteLine("We will start construction of the office on Monday");
break;
case 2:
Consle.WriteLine("We will start construction of the office on Tuesday");
break;
case 3:
Consle.WriteLine("We will start construction of the office on Wednesday");
break;
case 4:
Consle.WriteLine("We will start construction of the office on Thursday");
break;
case 5:
Console.WriteLine("We will start construction of the office on Friday");
break;
case 6:
Console.WriteLine("We will start construction of the office on Saturday");
break;
case 7:
Console.WriteLine("We will start construction of the office on Sunday");
break;
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 2 error(s), 0 warnings
main.cs(6,18): error CS1519: Unexpected symbol `Main' in class, struct, or interface
member declaration
main.cs(6,15): error CS1520: Class, struct, or interface method must have a return type
In the next example, you will see what error message is likely to be displayed if you miss out on
a symbol in a while loop.
using System.IO;
using System;
class Program1
{
static void Main()
{
int x = 0 // this is the initialization
while (x < 50) // here is the condition
{
Console.WriteLine("x = {0}", x);
x++; // this is the increment
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 4 error(s), 0 warnings
main.cs(10,0): error CS1525: Unexpected symbol `while'
main.cs(12,34): error CS0128: A local variable named `x' is already defined in this scope
main.cs(12,34): error CS1525: Unexpected symbol `)'
main.cs(17,0): error CS1525: Unexpected symbol `}'
A semicolon was missing in the above code sample. In the next example, I will remove () from
the while loop and see what results I receive.
using System.IO;
using System;
class Program1
{
static void Main
{
int x = 0; // this is the initialization
while (x < 50) // here is the condition
{
Console.WriteLine("x = {0}", x);
x++; // this is the increment
}
}
}
$mcs *.cs -out:main.exe
Compilation failed: 3 error(s), 0 warnings
main.cs(6,12): error CS0547: `Program1.Main': property or indexer cannot have void
type
main.cs(8,8): error CS1014: A get or set accessor expected
main.cs(17,0): error CS1525: Unexpected symbol `}'
Chapter Nine
Writing Secure Code
Programming is generally described as the process which leads a computing problem from the
original formulation to the executable program. The process generally involves different
activities such as analysis, developing understanding, generation of algorithms, and verification
of the essential algorithms including accuracy and the utilization of resources. It also includes the
coding of different algorithms in a particular programming language.
Many C# developers don’t write unit test methods for different non-public assemblies. C#
enables you to boost visibility in between assembly internals and other different assemblies.
Security is considered a big topic when it comes to coding and programming. When you have an
application in C#, the first thing you need to do is secure from application from being attacked
by malicious hackers or from being used for things it was not meant to be used for. At the start of
the electronic age, security is normally performed by the method of obfuscation. If you have
built an application and you want it to stay secure, you can hide it and no one will ever know
where to find it. It would remain secure.
Security is and ought to be considered an integral part of every system you write. It is possible
that your application may not contain any sensitive data, but will be used to get other information
that is saved on your machine? Attackers might use it to gain access to a network that you have
deemed forbidden.
The two major parts of security are known as authentication and authorization. Authentication is
defined as the process of making sure that a user has the authentication to access the application.
The most widely known method of authentication requires a username and a password. You also
can use a thumbprint method for the purpose. Authentication suggests that you ensure that a user
possesses the authority to do what he or she is requesting to do. File permissions are considered a
good example of this. Some app developers don’t let users delete system-only files.
However, there is more to security than merely usernames and passwords. This chapter will walk
you through how to make your C# programs secure from outside attacks.
Secure Design
Security usually takes a good amount of work while you are designing software. If you break
down the process into tiny chunks, you will find out that it would be a lot easier to accomplish.
You have to take up a systematic approach to ensure the security of your systems. Different
applications possess different artifacts that require protection, but all applications usually have
something that needs to be secured. If there is a database in your application, it is the most
important item for protection.
The server should be high-rated if you want better security. Even if you build a simple program
that is a single-user application, you must not let any outsider to a user the application for
breaking into the computer of the user.
Documentation
Describe what your application is. The description becomes a functional overview of the
application. Describe how your application accomplishes the tasks at the highest level. If you
take a look at a Software Architecture Overview diagram, you will know which services and
machines have what job to do.
When you have created the document that describes the job of the software, you must break out
different individual pieces of the software. If you have set up the software in the component
fashion, the methods and classes show functional decomposition. The final result of this breaking
down the software is taking a look at the individual pieces and decide which components must be
protected.
When you have created a list of components that you ought to protect, you must tackle the tough
part. You need to put two and two together. If your application tends to connect to a database,
you must imagine that this connection needs to be intercepted by some third party.
Threat Model
You must create a threat model for which you have to categorize different potential threats to the
software. The easiest way to remember different categories of threats is by using the STRIDE
method.
Security is more often described as a negative property. You can label a system as secure if there
is no danger of attack. To access the system’s security, you need to look at and analyze all the
possible threats that are posed against your system. The STRIDE model is considered a useful
tool to help you classify these threats.
Microsoft develops it to classify potential threats on the server. Each alphabet in the word
STRIDE represents a potential threat.
Spoofing
Most of the security systems tend to rely on the authentication and identification of the users.
Spoofing attacks largely consist of using another user’s credentials without his or her knowledge.
Typical spoofing threats target weak authentication mechanisms. It targets those that have
simple passwords like 4 digit password. Attackers access personal information quite easily such
as the place of birth and the date of birth.
Tampering
Only authorized users are allowed to modify a system or the data it uses. If an attacker can
tamper it, it results in some serious consequences on the usage of the system. If the attacker can
add or remove a bunch of functional elements, for instance, some important data gets destroyed
or modified.
Repudiation
Attackers need to hide malicious activity to avoid getting detected or blocked. They may try to
repudiate the actions they have already performed such as erasing them from the logs or by
spoofing different credentials of any other user.
Information Disclosure
Many systems keep confidential information. Attackers aim at securing and getting hold of that
information. It also is known as data breaches.
Denial of Service
A system is deployed generally for a particular purpose whether it be a banking application or
any kind of integrated media management that is installed on a vehicle. In some cases, attackers
will show interest in the prevention of regular users for accessing the system. This can be for
blackmailing a person or for extortion of money from the owner of a system. Ransomware is an
example of such a threat.
Privilege
Once a system identifies a user, they have some kind of privilege which is that they are
authorized for performing certain actions, but not all of the actions. An attacker might try to get
additional privileges by spoofing a user with higher privileges or just by tampering the system
and changing their respective privileges.
All these threats ought to be determined in a certain outline under the functions that would
expose the threat. The strategy gives you a discrete list of threats and also focuses the security
hardening on different parts of the application that would pose the greatest security risk.
You should rate the risk by defining what the potential for damage is. For example, you may
calculate the dollar cost of the company for the breach. You ought to calculate how far a
potential hacker can go in terms of exploiting our system. You also should calculate the number
of users who have been affected. Try to find out who they are. The level of difficulty by which
you can discover the threat also ought to be determined.
Common Mistakes
The most common mistake programmers make is using string concatenation technique in the
wrong way. In other programming languages, concatenation can be done by inserting a plus sign
between the strings. This is considered inefficient and fragile. C# offers StringBuilder method to
perform the same task. The method is useful for complex operations. For example, you can
deploy it if you have to concatenate one long list to another and display the output to the user or
channelize the output to a database for storage purposes.
The second most common mistake that programmers make is that they don’t log errors when
they are writing the code. You have seen that I carefully documented different kinds of error
messages that I received from the compiler, and presented them to you so that you can use them
as a reference whenever you see the same, and fix them. If you develop the habit of documenting
the error messages whenever the compiler throws one, you will be able to fix the errors in the
code faster than before. Log your errors and the next you will see one, you will know its
background.
The third mistake that can be easily avoided is using var despite knowing which data type is in
use. When you use var, you allow the compiler to decide upon the datatype of the variable. The
fact is that compiler may be wrong. It will not always detect the correct datatype. Better define
the datatype yourself. Besides decreasing the chance of error, it will improve the readability of
your code, which is better if a colleague in the office has to read your code for the purpose of its
betterment.
Conclusion
Now that you have made it to the end of the book, you should be able to practice the different
features of C# programming. The key lies in practicing more by using different variables and
methods. Experiment with the code and learn each step.
C# offers an immense variety of toolsets and different frameworks that you can use while
programming. Microsoft generally backs all these frameworks and toolsets. Any developer will
admit that Visual Studio is feature-rich and powerful development environments that exist in the
market. The .NET framework offers hundreds of libraries for the building of websites, working
with the file system and the implementation of security.
I hope that this book has equipped you with the right skills and techniques and that you will be
able to program by using C#. You can keep this book as a pocketbook that you can use whenever
you are writing or practicing a code. Take the sample codes as the right track to follow and
gradually learn. I have tried to keep the context of the book as simple and easy-to-read as I could
so that even a beginner may find in it the right material.
This book dealt with the most basic topics like strings, variables, data types, and other stuff like
that. You learned about the basics of C# like strings, substrings, and different properties of
strings. Strings and integers are the most common data types that you might have noticed on
several occasions in the code. I have used both of them in almost all of my codes. You have
learned about C# loops such as the while loop, do-while loop, for loop, and foreach loop. These
topics are really interesting and can help you create programs that involve mathematical
calculations. These types of elements are used in the programs that are created for cash counters.
They will do the math for you in the blink of an eye. You have also learned about C# arrays and
lists which are immensely helpful when you are creating a game in C#. You can allow the
players to be more interactive while playing the game. You have also learned about the most
important aspect of C# which is object-oriented programming (OOP). This chapter contained
classes that are used to model real-life objects in the world of programming. I created a dog, a
cat, and a car class for you to understand how you can create different objects and give them
certain features so that they can fulfill your specific programming needs. I hope you have
practiced this section quite well, and even if you have not, you should do that even if you have
now completed the book. You must be an expert at OOP; that’s why I have dedicated two
chapters for this section. C# classes have different features and you must get yourself acquainted
with them before you start writing your program.
References
http://www.scfilmvideo.com/download/temp/0470563486.For.Dummies.CSharp.2010.All-in-
One.For.Dummies.Apr.2010.pdf
https://www.w3schools.com/cs/cs_arrays.asp
https://www.w3schools.com/cs/cs_for_loop.asp
https://www.w3schools.com/cs/cs_user_input.asp ’
https://www.w3schools.com/cs/cs_conditions.asp
https://www.learncs.org/en/Lists#:~:text=Lists%20in%20C%23%20are%20very,called%20numbers%20which%
https://www.tutorialsteacher.com/csharp/csharp-list
https://www.w3schools.com/cs/cs_break.asp
https://www.w3schools.com/cs/cs_oop.asp
https://www.freelancer.com/community/articles/top-16-c-programming-tips-tricks
https://www.w3schools.com/cs/cs_classes.asp
https://www.w3schools.com/cs/cs_inheritance.asp
https://www.futurelearn.com/courses/cyber-security/0/steps/19631
C#
Advanced Guide to Learn C# Programming Effectively
BENJAMIN SMITH
Introduction
Object-oriented programming is like a rabbit hole; once you start to explore it, the tunnel only
seems to get deeper and deeper. This is especially true because of the family of programming
languages whose cores are based on object-oriented techniques and principles. C++, C, Java,
Javascript, PHP, Visual Basic, Microsoft .NET, Ruby, Scala, and a bunch of other programming
languages are all classified as ‘OOPL’ (Object-Oriented Programming Languages). In this
language family, C# is similar to that sibling who is difficult to get along with but incredibly
resourceful. C# is alluring and fascinating to some people, while to others, it is a real hassle to
learn and work with this language, but none of these two people at the opposite ends of the
spectrum are to blame.
People familiar with mainstream OOPL, such as C++, will find that C# has all those bells and
whistles that you would find in other object-oriented languages, ultimately making it easier to
learn C#, but even with these similarities, the implementation of the same techniques, tools, and
concepts are radically different, and on top of that, C# does not have one defined IDE, anyway.
At the same time, you can argue that no programming language has one IDE that’s better than
the rest. Still, in the case of C#, the result is an inconsistency in the programming experience, not
the case for other languages. Hence, trying to teach the reader a universal set of techniques and
practices is quite literally impossible. Even the fundamental concepts may be different, even
though you may be familiar with them from other object-oriented languages.
For this very reason, the first chapter of the book is essentially a review of the most important
programming concepts in C#. In this way, since all the readers will likely read this chapter before
moving on, everyone will have the same idea of the concepts that are being explained and used
in the upcoming chapters. This is very important because literally, every discussion being made
after chapter 1 builds upon the concepts that are highlighted at the very beginning. Even if the
reader already knows about all the concepts discussed in the first chapter, the chapter itself does
not become useless because it will still serve as an opportunity to review the knowledge that they
already possess. If there’s something that is not clear or is ambiguously explained, then do a brief
web-search. There’s a high chance that you might just need a small detail to understand what’s
being discussed in the topic.
Chapter One
Getting Familiar with the Foundations of C#
This chapter will provide the reader with an overall review of the most important concepts in C
sharp. This is necessary because the upcoming chapters will build upon the things we review
here. This allows the readers to become familiar with the idioms commonly used in advanced C
sharp programming (which will be quite frequently used in the upcoming chapters). In this way,
this chapter hopes to get the readers on the same page before we move on with advanced
programming techniques and projects in the latter half of this book.
However, if you already have experience with object-oriented programming languages like Java,
Javascript, C++, PHP, Visual Basic .NET, etc., you might think this chapter will probably not be
worth your time, but this chapter will prove to be a really useful checkpoint where you can
review the concepts you are already familiar with. On the other hand, most readers picking up
this book will find this chapter to disclose certain aspects of not only C sharp but also .’NET’
programming that they were previously unaware of.
In short, the content here will provide the readers with foundations necessary for understanding
the discussion of C sharp programming to create advanced applications throughout the course of
this book.
When exploring C sharp, we find out that the core of this object-oriented programming language
implements the principal elements with operator overloading, inheritance, interfaces, exception
handling, garbage collection, multiple interface inheritance, reflection, and multi-threading, but
you might notice that C sharp shuns a few functionalities such as templates, raw pointers, and
even multiple class inheritance. The reason why these functionalities were not included within
the C sharp programming language is because of the argument, which, on one side, supports the
claim that these features introduce more problems than they can potentially solve. On the other
side, the belief is that these are key components of any object-oriented programming language,
and the features they bring to the table are priceless, and they need to be included, but keep
things simple and straightforward, further complications were avoided by simply not adding
these features to C sharp.
However, this does not give much confidence to anybody who has any experience in
programming. This is because the feature set of templates, multiple inheritances, and pointers
greatly facilitates the user in Web application and Web Services projects. Hence, this might be a
monumental deal-breaker for some people, but C sharp does not disappoint their end-users. In
order to make up for the lack of such tools, C sharp includes its own feature set that can help
users to build Web Applications and Web Services. For instance, C sharp features a tool that
allows for hosting applications on the Windows platform, namely, ‘COM interop .’ Not only
that, but C sharp also boasts multilanguage programming as well as rapid application
development.
But through all this ramble, there is still good news. As we discussed before, all the object-
oriented programming languages have the same core principles with a difference in the features
implementing them. You will find that some features from other OOPLs carry on to C sharp. For
instance, if you are comfortable with the syntax of C++ or Java, then you’ll find that the syntax
of C sharp is strikingly familiar, thus allowing you to settle in considerably faster. This is just
one of the many similarities you’ll find in C sharp when comparing it to other object-oriented
programming languages, so it’s a good idea to make a quick comparison if you’re coming from
such languages.
In the upcoming sections, we will discuss the object-oriented basics and discuss the relative
features available in C sharp.
Defining Classes
Creating and defining classes is done the same way as you would in C++, albeit the underlying
construct of this action is slightly different in C sharp. The following syntax demonstrates the
construct required to define a class in C sharp.
Access-modifier class name
{
}
One thing to be mindful of is that just like C++, C sharp is a case-sensitive programming
language. Thus, you need to be vigilant of the case in which your classes have been defined
when referencing them. Otherwise, the compiler will not recognize which class you are referring
to.
The syntax demonstrated above has the potential of being confusing, so let’s clarify its elements.
The syntax has two elements - the ‘access modifier ’ and the ‘name .’ The second element is
self-explanatory, i.e., it is the set of characters by which the class is recognized, but the first
element's purpose is to define the scope of the class (you should already be familiar with
‘scopes’). Generally, classes are specified as ‘public ’ (which is the same as ‘global ’ in other
programming languages) so that they can be accessed by any function in any program, as long as
the header file is included (where the classes have been already defined).
So, if we replace the appropriate arguments in the syntax shown above, we will end up with
something like this:
public class MyFirstClass
{
}
In the curly brackets, you fit in your class's contents (the functions, methods, and objects it
includes). If you look a bit closer, you will see that the class's name has all the first letters of each
word capitalized. This is not random or a mistake. Instead, we follow a convention here when
naming classes. The purpose of a convention is to maintain consistency when programming,
which can be really impactful in the long run, but it is not mandatory to follow this naming
convention (known as ‘Pascal Casing’). It’s all up to you whether you choose to use it or not (the
same goes for other numerous conventions in programming).
Using a Class in a Console Application
Assuming that you have some knowledge of programming or any amount of programming
experience, then you must be familiar with the term ‘console.’ When you are using IDE software
to code, you will find a small window in the bottom that looks similar to that of a command
prompt, giving the user feedback information when they execute certain commands (such as
compile, debug, etc.). Moreover, a console will also display syntax errors in the code when asked
to compile the project you have opened currently.
Similarly, suppose we want to work with C sharp to code applications, etc. In that case, we will
do so by using an Integrated Development Environment (such as Microsoft Visual Studio), but
we are not to confuse a ‘console’ with a ‘console application.’ While a console is natively open
in an IDE at all times, a ‘console application’ on the other hand, is simply an executable file that
does not have a fancy GUI. The interface through which the user interacts with the application is
like a simple command prompt.
In such tasks, the most common action that you will likely perform during C sharp programming
is implementing the classes you have defined in a certain console application. We can easily
create a fresh console application by opening a ‘New Project’ within the IDE. The underlying
code for the newly created console application is as follows:
using System;
namespace HelloWorld
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start the application here
//
}
}
}
Now let’s break this code down a bit. At the very start of this code block, we notice a statement
being used, which is ‘using .’ The argument passed to this statement is ‘System .’ In this block
of code, ‘System’ actually refers to a .’dll ’ assembly file available through the .’NET
Framework ’ installed on our computer (using Windows, obviously). We do not need to go into
the details as to ‘why’ a fresh console application is using the ‘System.dll ’ assembly file. A
simple answer to this question of ‘why’ is that this file contains the necessary elements required
for ‘Common Language Runtime.’ It wouldn't be wrong if we even said that the .’dll’ file is the
console application itself. The ‘using ’ statement we use in C sharp is synonymous with the
‘include ’ statement in C++ and the ‘uses ’ statement in Delphi.
In the next step, we specify the ‘name ’ of the console application through the ‘namespace ’
statement. The argument passed to this statement will be the name we assign the project, which
in this case, would be the conventional name of the very first program created by a user, i.e.,
‘Hello World.’ However, in the argument, we do not add spaces in between a single namespace.
The ‘slash’ symbols that you see in the middle of this block of code represent comments.
Anything that is written after three/two slashes (\\\ or \\) is considered as additional commentary
made by the programmer. Comments can be really helpful either when you need to go through
the program's code later on its life cycle or if somebody else is exploring it.
After the initial three comments, we will see the very first class is defined. Since this is a code
generated when we create a default console application, the classes' names and constructs are
standard. It is recommended that you name a class you create something that is self-explanatory,
short, and easy to recall (although not every name can have all three of these elements).
Up next, we have the core element of the entire application, the ‘Main() ’ member. If you have
experience with C++, then you will be quite familiar with this member. Main is not a standard
member. In fact, it has a special property that turns it into what we call a ‘static member .’ The
property associated with a ‘static’ member is pretty useful. It allows us to use the method(s)
associated with such a member without having an ‘enclosing class’ to exist. In addition, an
argument known as ‘string[] args ’ tells us that a bunch of strings (in the form of an array) are
passed to the Main static member. These strings are basically the ‘Command Line Arguments’
that you will generally pass during a coding session.
Printing a Statement in a Console Application
Now that we understand the underlying elements of a console application let’s build one to
display a simple phrase, ‘Hello World!.’ To do this, we will simply be filling in the necessary
arguments to the statements shown in the code of a console application.
using System;
namespace HelloWorld
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.ReadLine();
}
}
}
To print out the phrase, we use two basic functions, namely, ‘Console.WriteLine() ’ and
‘Console.ReadLine() .’ We specify the phrase or sentence we want the console application to
display and pass it as an argument to the ‘Console.WriteLine() ’ function. Once this is done, the
‘Console.ReadLine() ’ function then stands by until it receives the carriage return it expects
before it continues with its job. The purpose of the ‘Console.WriteLine() ’ function is the same
as the ‘cout>>’ statement in the C++ programming language.
When analyzing the usage of the methods to print out the phrase “Hello World!”, you might
notice that these methods were used without including an instance of the corresponding ‘Console
object.’ If this were a normal scenario, then you would be absolutely right, but the truth is that
these methods are actually static members present in a class named ‘Console .’ So, if we want to
call upon and use these methods, then we don’t need to create an instance of the corresponding
class’s object.
Performing a ‘Read’ on the Command Prompt
We will now go over the approach through which we can effectively intercept the arguments
specified to the console application. To do this, we simply pass a special argument to the
‘Console.WriteLine() ’ method. This argument is ‘args[0], ’ and you can see it being
implemented in the following block of code:
using System;
namespace HelloWorld
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Console.WriteLine(args[0]);
Console.ReadLine();
}
}
}
When we execute this block of code, whenever we pass an argument to the command prompt, it
is intercepted by the console application displayed on the console.
Passing an argument to the command prompt can be done in two ways (there are other ways as
well, but for the sake of simplicity, we will just stick with two).
Execute an assembly through the command prompt and pass a corresponding
argument.
Using the Microsoft Visual Studio IDE to pass arguments to the command prompt.
Let’s get into some details regarding the second method. Using the .’NET Visual Studio’
Integrated Development Environment is not that complex since you must have experience with
other IDEs at this point. In order to use the IDE to pass an argument to the command line, we
need to perform the following actions:
1. Open the Visual Studio IDE and look for the ‘Solution Explorer’ menu inside the
‘View’ tab.
2. Once you are inside the ‘Solution Explorer’ menu, you will find a list of all the
projects that you have been working on or placed in the IDE’s browsing directory.
Over here, you need to find the project you want to work on for this task and then
just right-click it. This will open a drop-down menu, and from here, you select the
‘Properties’ option.
3. This will open a new window as shown below:
On the left-hand side, you will see a small file navigation interface. From here, double click
‘Configuration Properties,’ and inside, select ‘Debugging.’
4. In the 3rd category named ‘Start options,’ the first section will be ‘Command Line
Arguments.’ Over here, you need to specify an appropriate value. In this case, we
pass an argument ‘Debugging C#.’
5. Once we are done with passing a command-line argument, we can reboot the
application we have opened in the IDE manually or by pressing the ‘F5 key’ as the
shortcut key. Once the application runs using the IDE after a reboot, we will be
able to see the argument passed to the command prompt.
Using Fields and Properties
‘Fields’ and ‘Properties’ are elements that are interestingly related to each other, but before we
can discuss them, let’s first understand the underlying concept of ‘consumers’ and ‘producers’ in
programming. ‘Consumers ’ are those people that are the end-users of things like classes.
Similarly, ‘Producers ’ are those people that build these classes. An interesting thing to note
here that both a consumer and a producer are programmers.
Now with that clarified, let’s talk about ‘Fields .’ A ‘Field’ is simply a bunch of data that is
contained within a class. Conventionally, the fields of a class are never public. Instead, they are
set to ‘private’ by the producer, but there are times when consumers need access to the fields of a
class they are using, but, since the fields are private, they are hindered. This is where ‘Properties
’ come in. Properties have the nature of duality. To elaborate, if a consumer is using this
‘Property Method,’ it will be indistinguishable as if the consumer were dealing with data. On the
other hand, if the producer uses the same property method, it will function as if it were a method.
You might ask why you would even need access to the data fields of a class in the first place.
Well, the answer to that is very simple and straightforward, having access to the data of a class
allows the programmer to have the freedom to make changes to the class’s methods and even
perform some tweaks to the class's objects. Similarly, using ‘Properties ’ allows us to control
how the data in the class is accessed.
Defining a Field
The nature of a field, i.e., the type of data it contains, can generally be anything (it just needs to
conform to the purpose of the class in which it will be used). Since this data is important to the
class, it is generally kept private through the use of access modifiers (i.e., setting its scope to
‘private’). In this way, only the programmer who created the field (the producer) will be able to
make changes to it. If anyone other than the producer wants to access the fields in a class and
make changes to it, they will have to do so through ‘Property Methods.’
In the following block of code, we are creating a field that stores string data.
using System;
namespace HelloWorld
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
private static string arg0 = null;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
arg0 = args[0];
Console.WriteLine(arg0);
Console.ReadLine();
}
}
}
In this demonstration, you can find that we are not using an instance of ‘Class1 ’ in this program.
Now let’s modify this block of code a bit such that we actually use an instance of the
corresponding class while it essentially performs the same job.
using System;
namespace HelloWorld
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
private string arg0 = null;
public void WriteCommandLine( string arg )
{
Console.WriteLine(arg);
Console.ReadLine();
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Class1 = new Class1();
class1.arg0 = args[0];
class1.WriteCommandLine(class1.arg0);
}
}
}
Basically, the revision involves how we use the ‘Main()’ method. Originally, this method
handled the majority of the work to perform the corresponding job, but we changed the purpose
of the ‘Main()’ method in the revision such that it’s the only job would be to act as a ‘startup
method’ only. To account for the changes in the way the code works, we implement an instance
of ‘Class1 .’
Defining Properties
Due to their nature and function, ‘Properties’ are basically considered as ‘methods’ (you might
have guessed it when we talked about ‘Property Methods’ in the previous sections). Generally,
properties can be used in one of two ways, either as a ‘right-hand side value ’ or as a ‘left-
hand-side value .’ If the property is being used as an RHS value, we call a specific property
method known as ‘getter .’ On the other hand, if the property is being used as an LHS value,
then the corresponding property method we call is known as a ‘setter .’
Properties also have access to modifiers defining their scope. Conventionally, properties are set
to public. Here’s how a property would be defined:
Access-Modifier Type Property-Name
{
get
{
return field;
}
set
{
field = value;
}
}
In essence, the property has three basic elements - an access modifier (which is generally set to
public), a ‘type,’ and last but not least, a name.
‘Properties’ can be of three types based on their use and implementation, i.e., ‘Read-only
Properties,’ ‘Indexed Properties’ and ‘Write-only Properties.’ Before moving on, let’s discuss
these different types of properties.
Read-Only Properties
The main element through which we can distinguish a read-only property is from observing if it
possesses a ‘getter’ or a ‘setter.’ If the property only has a ‘getter’ then it is a ‘Read-only
Property.’ Just like the name suggests, such properties only allow the users to view the property
elements, such as its values, and the user has no authorization to make any changes.
Here’s an example where we access the value of a ‘Read-only Property’ for the temperature
defined in a class. This temperature class features readings in both Celsius and Fahrenheit scale.
Here’s how we can use the Read-only Property to fetch the scale in which the corresponding
class's temperature will be displayed.
public enum TemperatureMode
{
Fahrenheit, celsius
}
class Temperature
{
private TemperatureMode mode = TemperatureMode.fahrenheit;
private double celsius = 0;
private double fahrenheit = 0;
public Temperature( double aTemperature, TemperatureMode aMode )
{
mode = aMode;
SetTemperature(aTemperature, aMode);
}
private void SetTemperature(double aTemperature, TemperatureMode aMode)
{
if( aMode == TemperatureMode.fahrenheit )
{
fahrenheit = aTemperature;
celsius = FahrenheitToCelsius(aTemperature);
}
else
{
celsius = aTemperature;
fahrenheit = CelsiusToFahrenheit(aTemperature);
}
}
public static double CelsiusToFahrenheit(double celsius)
{
return celsius * (9.0/5) + 32;
}
public static double FahrenheitToCelsius(double fahrenheit)
{
return (fahrenheit - 32) * 5.0/9;
}
public TemperatureMode Mode
{
get
{
return mode;
}
set
{
mode = value;
}
}
public double Value
{
get
{
return mode == TemperatureMode.fahrenheit ?
fahrenheit : celsius;
}
}
public bool Test()
{
return fahrenheit == CelsiusToFahrenheit(celsius)
&& celsius == FahrenheitToCelsius(fahrenheit);
}
}
To determine the scale on which the temperature will be converted to (in simpler terms,
determining whether to use the Celsius scale or the Fahrenheit scale), the block of code shown
above executes a corresponding enumeration.
Write-Only Properties
Just as a property with only ‘getters’ is the defining feature of a ‘Read-only Property,’ a property
that only has ‘setters ’ is primarily known as a ‘Write-only Property .’ In such a type of
property, a user accessing the class can make changes to it and even to the property itself.
Usually, you won’t come across write-only properties as much because they are not often used,
as it can cause unnecessary complications due to the modification privileges given to the end-
user.
However, this does not mean that write-only properties are entirely useless. For example, you
can use the functionality of write-only properties for tasks such as requesting authentication from
the user in the form of a passcode. Instead of using a read-only property to display the
authentication code to the end-user, it would be better to use a write-only property and allow the
user to type the correct passcode in by themselves.
Indexed Properties
This type of property is also simple, like the other two. Just as the name ‘Index’ suggests, this
type of property is primarily used to communicate the items which have been placed in the
corresponding class in the form of a ‘list.’ Since the main user will be a consumer, the form in
which the requested data is displayed is in the form of ‘object[index] .’
Here’s a demonstration of the use of ‘Indexed Properties.’
class IndexedProperty
{
private string[] args = null;
public IndexedProperty(string[] args)
{
this.args = new string[args.Length];
args.CopyTo(this.args, 0);
}
[System.Runtime.CompilerServices.IndexerName("Command")]
public string this [int index]
{
get
{
return args[index];
}
set
{
args[index] = value;
}
}
}
Using an Instance of a Class
In order to create an instance of an object and then have it run in the program where it was
created, we need to call upon a ‘Constructor’ with the help of an operator. When we create an
instance of an object, we can take a bunch of variables and link them to the instantiated object,
but there’s a condition to perform this action: whenever we try to assign a variable to an object,
both elements need to be compatible with one another. The instantiated object’s type and the
variable’s type need to be similar, to be more precise. This linking process will fail if the types of
the object and the variable do not match. The type compatibility even extends to the object’s
predecessors. By predecessors, we mean those objects whose features this object instance
inherited. So, if the variable’s type matches any of the object’s ancestors, then it can be assigned
to the object. In other words, if we have a variable that was previously declared to be of the same
type as an object’s ancestor, then we can use this variable with the very same object’s child
instance as well.
If we want to create an instance of an object, we will need to use a ‘Constructor.’ A constructor
is basically a method that is primarily used during the process of creating an object (this includes
creating an instance as well). A constructor has three elements, a name, an access modifier, and
parameters. The name of the constructor is usually the name of the class to which it belongs to.
The access modifier can be either public or private, and it can have numerous parameters or
none.
The following example shows the process of creating an object instance with the help of a
constructor.
// simple object creation
FileStream fs = new FileStream("c:\\temp\\killme.txt", FileMode.CreateNew);
fs.Write(new Byte[]{65, 66, 67, 68, 69}, 0, 5);
fs.Close();
// array examples
string[] strings = new string[10];
strings[0] = "Some Text!";
int[] integers = new int[]{0,1,2,3,4,5};
Defining an Interface
In the context of object-oriented programming languages, an interface isn’t any different from
what you might actually be familiar with. The main use of the interface is to create a method of
interaction for a specific class. To be more precise, an interface is an actualization of tapping into
the functionality of a class. Consider a sound system installed in a vehicle. This sound system
has two circular controllers that can be rotated to navigate through the menu, increase or
decrease the volume, change the radio station, or even shuffle through songs being played
through external media. Now, let’s narrow things down a bit. Let’s say that these hardware
controllers allow you to tune the radio station, and you can also do this without having to use
these knobs as well. For instance, you can have a small infrared controller that can do this task
for you. In this scenario, the tuning of the radio stations is done through an underlying interface,
and we can access the functionality of this interface through external tools. If you think about it,
the sound system's volume is controlled through a specific ‘volume interface.’ We can connect to
this interface to leverage its volume changing functionality through an infrared remote, hardware
buttons, or even voice control. As such, the hardware buttons controlling the volume are seen as
the ‘physical controls.’ The aspect we are controlling is ‘volume,’ which is known as the
‘attribute.’ We manipulate this ‘attribute’ by implementing either ‘Methods’ or ‘Property
Methods’, and these methods act as the supporting framework of an interface.
Here’s how you can easily define an interface.
public interface IAudio
{
void AdjustVolume( int value );
}
Implementing an Interface
Once we have created an interface, we still need to implement it properly in a program or
application. Generally, interfaces are implemented within classes. When implementing an
interface, it should always be remembered that all the interface methods will be implemented as
well.
To implement an interface, simply specify the class you want it to be in. The following block of
code shows us how we can implement an interface within a class:
public interface IAudio
{
void AdjustVolume(int value );
}
public class Radio : IAudio
{
private int volume = 0;
void IAudio.AdjustVolume(int value)
{
volume += value;
}
}
In this code, the interface we are implementing is ‘IAudio, ’ and the class in which we are
implementing it is ‘Radio .’ The process is simple. First, we write the access modifier of the
concerned class, then type its name, then place a colon after the class’s name (:) and finally,
specify the interface's name. This has been demonstrated in the 3rd line of the code block.
Inheritance
The concept of inheritance is almost universal, be it in biology or computers. Inheritance is
basically when a class passes on its features and certain characteristics to another class, but the
result is not going to be a completely identical copy of the original class. The inheritance
relationship usually involves two or more than two classes. The class whose features are being
inherited is known as the ‘superclass, ’ and the class which is inheriting those features is known
as the ‘subclass .’ Think of it as the relationship of a parent and a child, in this case, the first one
(superclass) would be the parent class and the second one (subclass) would be the child class.
Like we discussed before, we are not simply making an identical copy of the original class.
Instead, the subclass has its own unique features, and it simply inherits the corresponding fields,
properties, and methods belonging to the original superclass.
However, to make the inheritance work, we must also know how to denote it in our code
properly. Let’s say that we are dealing with two classes, ‘Class X’ and ‘Class Y.’ If we say that
class Y inherits the members of class X , then we would denote this inheritance relationship in
the following syntax.
Public class B : A
Here is a list of some important inheritance concepts that you always need to remember.
The class from which the features are inherited is the parent class, and the class
which inherits those said features is the child class. For example, If ‘Class Y ’
inherits the members of ‘Class X,’ then ‘X ’ is the Parent and ‘Y ’ is the Child.
If class Y inherits the members of class X , then class X is referred to as the
‘superclass, ’ and class Y is referred to as the ‘subclass .’
The process of ‘Inheritance ’ is sometimes also referred to as ‘generalizing .’
If the inheritance relationship has multiple children, then the relationship of each
child with each other would be termed as ‘siblings .’ So, multiple classes that
inherit their members from the same superclass are termed as ‘siblings .’
Here’s an example of using the Inheritance feature, where multiple classes are inheriting the
members of the ‘Radio Class ’, which, in this case, would be known as the parent class.
public interface IAudio
{
void AdjustVolume(int value );
}
public class Radio : IAudio
{
private int volume = 0;
void IAudio.AdjustVolume(int value)
{
volume += value;
}
public int Volume
{
get
{
return volume;
}
set
{
volume = value;
}
}
private double station = 94.1;
public double Station
{
get
{
return station;
}
set
{
station = value;
}
}
public void Receive()
{
}
}
public enum RadioBand
{
AM, FM
}
public class AMFMRadio : Radio
{
private int volume = 0;
void IAudio.AdjustVolume(int value)
{
volume += value;
}
public int Volume
{
get
{
return volume;
}
set
{
volume = value;
}
}
private double station = 94.1;
public double Station
{
get
{
return station;
}
set
{
station = value;
}
}
public void Receive()
{
}
}
public enum RadioBand
{
AM, FM
}
public class AMFMRadio : Radio
{
This might be a little confusing for you because there are multiple instances of inheritance going
on, but the core concept remains the same. In this example, we have a parent class (superclass),
‘Radio ,’ and two child classes (subclasses), ‘CommunicationsRadio ’ and ‘AMFMRadio .’
These sibling classes inherit the important members of their parent class in order to perform their
own unique functions. For the ‘CommunicationsRadio ’ class, it would be to enable the
functionality of transmitting and receiving radio signals, and for the ‘AMFMRadio ’ class, it
would be to support different Radio Bands, i.e., Amplitude Modular Bands (AM) and Frequency
Modular Bands (FM).
Encapsulation and Aggregation
Both ‘Encapsulation’ and ‘Aggregation’ indicate the affinity of a class (or any data structure) to
be stuffed with members, but both these terms are not the same. While encapsulation refers to the
affinity of a class to withhold members within itself, aggregation includes those members that
are classes themselves (or data structures). If the concept of encapsulation is still confusing, then
consider an analogy. Think of the small leaflet that has small compartments holding medicine
tablets. The medicine is ‘encapsulated’ in the leaflet. In this analogy, the ‘medicine’ is actually
the ‘class,’ which has the methods, functions, and objects, and the leaflet represents the
‘encapsulation’ method. Through the use of encapsulation and aggregation, we can essentially
put data in a class while controlling the authorization to access it. With encapsulation, we can
add simple data types and structures. With aggregation, we can add more complex data types and
structures inside a class.
However, we cannot just throw data randomly inside classes. We need to think about which class
is the best container for our data. One way of going about this is to look through the list of
classes available to you and determine which is the most suitable contender, i.e., which class is
inherently responsible for holding a specific type of data. For example, if we consider the human
lungs as ‘data,’ then it would make more sense to put them inside a ‘human body (class)’ rather
than in a plant (another class).
Let’s use the ‘Radio ’ class to explore how we can implement ‘Encapsulation’ and
‘Aggregation.’
public class BoomBox
{
private AMFMRadio radio;
public AMFMRadio Radio
{
get
{
return radio;
}
}
BoomBox()
{
radio = new AMFMRadio();
}
}
In this code block, we are working with a new class that we haven’t previously used called
‘BoomBox .’ The interesting part is that this class actually contains the ‘AMFMRadio ’ class.
As such, the ‘AMFMRadio’ class is representing the process of encapsulation as well as
aggregation.
Polymorphism
The concept of ‘Polymorphism’ in C sharp is actually not that complicated. Polymorphism is
basically involved when a programmer encounters a problem that can be handled by any general
‘provider.’ However, the catch here is that the provider must be part of a bigger set of providers.
This means that our problem can be solved regardless of whichever provider we choose from this
collection. This is known as ‘Polymorphism, but just understanding polymorphism from this
perspective might not do you any good so let’s take a more technical approach.
First, let’s take a class and declare it as a general type. When we generalize a class, it basically
inherits the type of its parent class (the superclass). If we want to take this class and create
several instances and want each instance of the class to have a type, we specify and not a general
type, this is our ‘problem.’ The notion of this being a ‘problem’ might seem silly, but it's to help
you understand the concept of ‘polymorphism.’ We can solve this problem by choosing a type
from a selection of different ‘types.’ Choosing any one type will solve the problem, but we still
have a wide selection we can choose from. This is ‘polymorphism’ where we first declare a class
of a ‘general type’ and then declare instances with specific ‘types.’ This phenomenon can be
easily observed in the working of the ‘EventHandler delegate .’ The delegate is instructed in a
way such that its initial parameter will be an object. Since this is the first parameter, the class
harboring the object will be considered as a ‘root’ for all the upcoming classes that will be used.
So, this means that the delegate can virtually take any object as the first parameter to satisfy the
need to specify a root class.
Access, Class, and Member Modifiers
Let’s first talk about ‘Access Modifiers .’ To put it simply, access modifiers define what the
users of a class can see and access. If the access modifier of a class is set to ‘private ,’ then the
consumer will not be able even to see the class, much less try to access it. If the access modifier
is set to ‘public ,’ then the consumer will be able to see the class as well as access its contents
and make changes to it.
The practical use of access modifiers is allowing for guiding a user during their programming
session. If someone is using your class in their code, then keeping those classes ‘private’ that do
not require any attention from the consumer will focus the concentration primarily on the classes
that have been purposefully kept ‘public’ by the producer. In this way, the producer ensures that
the consumer only tinkers with those classes that need interaction in order to use them.
In C sharp, there are a total of five access modifiers that you can use. These access modifiers
have been listed below, accompanied by brief explanations.
1. Public Access Modifier : this modifier provides the end-user with the freedom to
access the members of the corresponding class (this also includes the ‘types’ in the
class as well).
2. Protected Access Modifier : this access modifier is generally used with classes
that are nested (a class within a class). As such, the subclasses (child classes) will
be able to access the members of the superclass (parent class) and other classes
within the nest, but the same level of access is not given to consumers. Instead,
they will be restricted from accessing the members of the nested classes.
3. Private Access Modifier : any members of a class that have a private access
modifier cannot be accessed by any subclass (child class) or any other user except
for the one who created the class.
4. Internal Access Modifier : a class whose members and types have their access
modifier specified to ‘internal ’ have their access restricted only to the assembly
in which they are present. In this way, any external will not be able to access these
classes, or members and the code will be able to communicate with the members
and types of classes.
5. Protected Internal Modifier : this access modifier is basically the result of
slapping the protected modifier on top of the internal modifier. Just as how a
protected access modifier would generally be used in nested classes, the protected
internal modifier is mostly used with nested types as well. Only the assembly has
unrestricted access to the members of the nested classes in a protected internal
modifier.
However, there are some rules you need to follow when using access modifiers in order to avoid
generating errors.
Whenever you are defining a high-tier type, its access modifier must always be
specified to ‘Public.’ Otherwise, it will surely cause complications when other
types need to communicate with the high-tier type. If you do not want to use the
‘Public’ access modifier, then the only other option you have is to use the
‘Internal’ access modifier.
Whenever you are dealing with nested classes or types (in a nested class, a class
contains another class. Similarly, a nested type is a type that holds the definition of
another type), you have to choose between either using the ‘Private’ access
modifier or the ‘Protected’ access modifier.
Even though ‘Protected Internal’ is a combination of two access modifiers
(protected and internal), it is highly advised to avoid combining any other access
modifiers in this way.
If a class or a type is not specified with any access modifier, then a ‘default access
authorization’ will be given to the corresponding members, but it is not
recommended to rely on this. Producers should always specify the appropriate
access modifier.
The concept of using modifiers with Classes and Members has already been discussed in one
way or the other when we talked about access modifiers. Regardless, if you find that the class
you have defined is enclosed within a namespace, it is best to set its access modifier to either
‘Public’ or ‘Internal.’ When working with nested classes, your options are limited as to which
access modifiers you can use to define them. These options include ‘protected, protected
internal or private’ access modifiers.
Members give the producer the freedom of assigning any access modifier to them. If you do not
specify any access modifier, then it will be set to private by default.
Reflection
This is basically a functionality that is largely used in the .’NET Framework .’ By using
‘reflection,’ a user can explore a program’s assembly to extract data in the code, which can
include.
Namespaces
Interfaces
Classes
Methods
Properties
Fields
Apart from that, reflection is an extremely useful object-oriented function that allows users to:
Execute ‘IL ’ (Intermediate Language) code during a program’s run-time.
Use special methods that allow for the viewing of metadata values recorded in
attributes.
Do some detective work, for instance, exploring the types defined in the corresponding assembly
and uncovering the members.
Chapter Two
Working with the Assembly
Viewer and UserControls
In the very last section of the previous chapter, we briefly discussed the object-oriented function
‘Reflection.’ This chapter extends the discussion and allows the reader to explore the practical
use of ‘Reflection’ to examine the data contained within the assemblies.
This entire chapter's core concept is based on dynamically loading the assemblies and using
Reflection to explore this assembly using the assembly viewer. The main take away here is that
understanding the process of loading assemblies and using them gives huge potential beneficial
uses. For instance, we can wirelessly load assemblies using HTTP connections, and by lightly
programming the client, we can automate two tasks:
Aside from this, we will also explore a number of other topics in this chapter, such as creating
and declaring static methods, using interfaces like IEnumerator, and practically demonstrating
the use of inheritance.
In the end, we will also explore the functionality of UserControls to create the buttons, icons,
and actions that you see designed in many Windows applications.
In the extensive list shown above, implementing the ‘using ’ statement has already been
demonstrated. If you have any experience with C++, then you can think of the ‘using ’ statement
as the ‘include ’ statement. If C# is your first object-oriented programming language exposure, it
will help you understand the purpose of the ‘using ’ statement as a tool that helps you bring in
external references to your assembly, but take note that it will be stored within a file with the
extension .’DLL’ whenever you are working with an assembly. So, if we use the ‘using ’
statement to add an assembly itself, we are essentially bringing in a .’DLL’ file. Moreover, this
statement can also be used to point to specific classes or functions that belong in a general
assembly file. If we want to use ‘Reflection,’ we will have to refer to the appropriate assembly
file.
using System``.Reflection;
The assembly we are referring to is ‘System.dll, ’ and the class we are using ‘System.Reflection
’ is part of the assembly file.
If we want to use the controls to access the Windows Forms functionalities, then we will have to
include the corresponding assembly file (System.Windows.Forms ) in the program first.
We can also implement the ‘using ’ statement to create a reference for a namespace. Whenever
we specify this ‘reference,’ the code will automatically interpret it as the namespace it is linked
to. For example,
using System.Diagnostics;
to
using Diag = System.Diagnostics;
Whenever we use the term ‘Diag ,’ the program will see it as the ‘System.Diagnostics ’
namespace.
Before moving on to the next section, we will discuss one final use of this directive. Let’s say
that you are implementing the ‘using ’ statement to create a block using an object you have
specified. If the ‘using ’ directive is implemented explicitly with the object that the block will be
using, then once this block ends, the object will be thrown away by the program. This will
continue to happen regardless if there is an exception before the block finishes executing. Here’s
a demonstration.
using (FormAbout form = new FormAbout())
{
form.ShowDialog();
}
Once this simple code block finishes executing, the object will be thrown away.
Working with the Assembly Using Reflection
The main element which is arguably the one that does most of the work for the entire
‘AssemblyManager ’ class is none other than the function ‘Load() .’ This function primarily
utilizes specialized objects, known as enumerators, to perform two tasks (using a different
enumerator for each one):
Going through every type which has been specified in the assembly and loads
them.
Going through the corresponding members of each type previously explored and
then loading these members.
By creating specialized looping structures in a program (for instance, a nested loop), we can
effectively iterate over all of these types and their respective members, thus extracting this
information. Once the function has gathered the necessary information, it then converts it into a
tangible form, like a string, and then displays it to the user. This gives the end-user a much-
needed insight for designing and creating elements such as an interface for a class.
Before we move on, let’s briefly discuss enumerators. Consider that you are presented with data
stored in the form of a list or an array, and you are asked to design a program that will go
through each entry in the data structure and perform a certain task. Traditionally, the first
approach that you might consider is to create a loop for such a task. To do this, you would create
statements using either ‘for ’ or ‘while .’ However, we know that the construct of such a
directive is essentially a ‘statement .’ If we want to use a method to execute a certain task when
the program is iterating over the data, we will need to pass certain parameters to the
corresponding method, but methods do not accept statements as their parameters. This is where
‘enumerators ’ come in. Enumerators are simply objects that can be used for special tasks such
as looping through a table of data, an array, a collection of strings, etc. Basically, enumerators
are used along with an algorithm. So, you take an enumerator, pass it to a method as its
parameter, and specify the algorithm the method will use.
If you want to use the ‘Load() ’ function, you will first have to know about its syntax and define
it in your program. If you look at the Assembly Manager’s code listing at the beginning of this
section, you will find the load function's definition beginning from ‘line 69 to line 90 .’ If we
bring our attention to line number 70 on the code listing, we will find that the function definition
includes creating an object instance named ‘StringBuilder .’ An instance of this object is created
seemingly effortlessly because it has already been defined previously (you will find the
definition if you look through the namespace ‘System.Text ’). The purpose of this object is to
boost the logistics of the converted string characters. To be more precise, a lone string buffer
available to the ‘StringBuilder ’ object has a considerably larger capacity. Thus, a larger volume
of string information can flow through the buffer, making string operations even faster.
Now let’s proceed with discussing how we can actually use Reflection. The first requirement is
to select an appropriate instance of an object from the assembly file we are working with. Once
we have the object instance in our sight, we essentially have the assembly’s reference. From this
point, all we have to do is simply employ Reflection, and the assembly will reveal all the
members that have been defined within it, but things are a bit different if we are dealing with a
type instance instead of an object instance. As we know, the members of each type are specific to
their unique elements (for instance, a type that only has members referring to ‘Methods’ and
other types referring to ‘Field’ information, etc.). So, when we use Reflection on a type instance,
then we will extract information that it refers to. Hence, if we want data regarding Methods,
Fields, Events, Properties, etc. then we will have to use Reflection on the respective type
instances.
Although we know what to do when we have an object instance, however, we do not know how
we can summon the object instance in the first place. Well, there are largely two methods
through which we can extract an object instance.
1. Using a method ‘AssemblyLoadFrom() .’ The argument to be passed to this
method is the name of the assembly we are working on.
2. Using a static method ‘Reflection.Assembly.GetcallingAssembly() .’
With either of these two methods, we can essentially extract the reference to the assembly we
want to work on. Once you obtain the reference, you now need to use appropriate methods to
perform certain actions on this assembly file. For instance, if we have an assembly reference and
want to extract information that tells us all the types defined in this assembly, we will have to use
the appropriate methods. In this case, we will first have to pass an array declaration and set the
‘type’ of this array to the types we want to extract from the assembly. Once the array is set up, all
we have to do is call upon the method ‘assembly .GetTypes() .’ However, you need always to
remember when using this method that the part ‘assembly ’ basically is the actual assembly
reference you previously obtained.
There’s more to the functionality of ‘Reflection ’ than just simply unraveling the contents of an
assembly. When we use Reflection to extract information regarding the types and members
contained within the assembly, at this point, Reflection is capable of using them as well, even
though their definitions are in the assembly file. Here’s a demonstration of how to load an
assembly file and using reflection to execute a static method which is originally from the
assembly itself.
const string s =
"c:\\winnt\\Microsoft.NET\\Framework" +
"\\v1.0.3705\\System.Windows.Forms.dll";
Assembly = Assembly.LoadFrom(s);
Type type = assembly.GetType(
"System.Windows.Forms.MessageBox", true);
type.InvokeMember("Show", BindingFlags.Public |
BindingFlags.InvokeMethod |
BindingFlags.Static, null, null,
new object[] {"Invoked by Reflection"});
The ‘Broadcaster’ Class
If you go through the Assembly Manager’s code listing, you will come across this somewhat
unique statement utilizing a class which most of you would not have seen before.
Broadcaster.Broadcast
This statement essentially uses the ‘Broadcaster’ class to literally ‘broadcast’ information to a
designated target. Any other user who intercepts this broadcast can access the information being
propagated as well. Such an approach is commonly used to send out information such as an
ongoing operation's current progress. For this, the class would essentially need to define a ‘main
form’ as the application that will receive the broadcast and display the information. We can see
the ‘AssemblyViewer ’ use this same approach to display its current status while an operation is
ongoing.
Here are the ‘Broadcaster ’ class and the necessary interface for receiving the broadcast.
1: using System;
2: using System.Collections;
3:
4: namespace AssemblyViewer
5: {
6: /// <summary>
7: /// Summary description for Broadcaster.
8: /// </summary>
9: public class Broadcaster
10: {
11: private static Broadcaster instance = null;
12: private ArrayList listeners = null;
13: protected Broadcaster()
14: {
15: listeners = new ArrayList();
16: }
17:
18: static private Broadcaster Instance
19: {
20: get
21: {
22: if( instance == null )
23: instance = new Broadcaster();
24: return instance;
25: }
26: }
27:
28: public static void Add(IListener listener)
29: {
30: Instance.listeners.Add(listener);
31: }
32:
33: public static void Remove(IListener listener)
34: {
35: Instance.listeners.Remove(listener);
36: }
37:
38: public static void Broadcast(string message)
39: {
40: IEnumerator enumerator = Instance.listeners.GetEnumerator();
41: while(enumerator.MoveNext())
42: {
43: if(((IListener)enumerator.Current).Listening())
44: ((IListener)enumerator.Current).Listen(message);
45: }
46: }
47: }
48:
49: public interface IListener
50: {
51: bool Listening();
52: void Listen(string message);
53: }
54: }
Can essentially link any class with the ‘IListener ’ interface and the class will gain the ability to
intercept the string information that is being sent to the target location, but to do this, the class
needs to implement the interface and register with the class that is ‘Broadcasting .’
Using the ‘Broadcaster’ Class
Now let’s understand how we can effectively implement this class in an application. Before that,
the reader must always remember that ‘Broadcaster ’ belongs to those groups of classes that
would ideally want only one instance of their respective class running. Such a group is known as
‘Singleton .’ So, the broadcaster class isn’t built like other classes. In order for it to function as
the other singleton classes, it has a ‘Private Instance Property .’
In the entire class, you will find that there are numerous public methods available, but we must
keep in mind that every single one of these ‘public methods ’ is, in fact static . Whenever a
public member from the broadcaster class is called, the corresponding method first and foremost
checks with a property named ‘Instance ,’ and this property is set to ‘read-only ,’ so the method
can access it but not modify it. This property then double-checks whether the broadcaster class
has any instances created and if so, then how many are there. So, if the Instance property
confirms that there is no ‘singleton ’ instance of the broadcaster class, then it proceeds to create
one. This newly created instance of the broadcaster class is then passed on to a field (set to
private) whose name is ‘instance .’ If the Instance property confirms that a singleton instance of
the class is already present, it then links the instance to the same private class. Once done, an
object from the singleton instance of the class is given by the Instance property. The end product
of all this skirmish is that the broadcaster class ends up with an object that refers to the
broadcaster class's singleton instance.
Lastly, there are two important elements left,
The IListener Interface - we can add this interface to an array defining the parts
of the system that are tapping into the broadcast. Once the interface is added to the
listener’s ‘ArrayList ,’ we can now execute the broadcast() method. Whenever
we do so, every listener in the array will have the broadcaster information
propagated to it.
The IEnumerator - we use an enumerator as opposed to using a ‘for, while ’ loop
statements to have the method loop through the entire list of listeners defined in
the ‘ArrayList .’
In order to use the broadcaster in your application, all you have to do is implement the
‘IListener ’ interface with a class that you want to receive the broadcasts. The following block
of code demonstrates how to use the ‘IListener ’ interface in order to use the broadcaster class.
public class FormMain : System.Windows.Forms.Form, IListener
{
private void FormMain_Load(object sender, System.EventArgs e)
{
Broadcaster.Add(this);
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
Broadcaster.Remove(this);
base.Dispose( disposing );
}
void IListener.Listen(string message)
{
ChangeStatus(message.Trim());
}
bool IListener.Listening()
{
return true;
}
}
Only in the ‘FormMain.cs’ module of the AssemblyViewer. We can use these controls to create
interfaces for fully fledged applications using the .NET Framework , but we cannot fully list the
module's entire code since it contains over 400 entries. Due to this, we will see portions of code
shown from this module.
Let’s start things off by simply adding the element of ‘Form Controls’ in an existing project.
Whenever a form is included in a program, the primary namespace used in the project is
essentially extended to cover the class responsible for defining the ‘form ’ as well. As such, we
do not need to create a separate namespace when adding a form control. The syntax for including
a Windows Form Control has been shown below:
public class FormMain : System.Windows.Forms.Form, IListener
Once you begin using Form Controls in your programs, you will come to notice that the
underlying syntax of adding a ‘form control’ is actually based on ‘Inheritance .’ This is because
for each ‘form control’ added to the project, the syntax creates a class that inherits from
‘System.Windows.Forms.Form .’ If we were to explain just the syntax shown above, then it
would essentially say that the class ‘FormMain ’ is supposed to inherit its members and types
from the assembly file ‘System.Windows.Forms.Form .’ Finally, this simple line of code also
implements the ‘IListener ’ interface as well.
If you use the ‘Visual Studio .NET ’ as an IDE for C# programming, then in this case, you will
find great convenience in implementing Windows Forms in a project. This is because with
Visual Studio .NET, you have two options when working with Windows Forms Controls:
1. Code view: just as the name suggests, the IDE shows you the underlying codes
responsible for the shape, size, and contents of the ‘form control.’ You can change
its elements by manipulating the code directly and include additional controls by
adding the corresponding code.
2. Form view: in this option, Visual Studio .NET provides the programmer with a
purely graphical view of form control being added. In this mode, you can
manipulate the form control elements directly by interacting with the IDE
interface. You can also add other form controls through the options provided
within the IDE itself. This provides an intuitive way for people to work with form
controls without having to interact with the corresponding code too much.
The direction of the moving elements is the one that determines the transposition of the
arguments. The enumerator is used to transfer all the selected items from the source to the target
and then RemoveSelected is called upon. An integer is used in lines 31 and 32 where
GetSelected and RemoveAt are defined as such that they only take an integer.
The feature of ListBox includes storage of objects in the list through a special collection thus
adding to the optimization of memory. Even still there is a downside to this, which is observed in
managing the movement of items between lists, more specifically faced when writing general-
purpose utility.
Windows has developed tools in the now not-so-recent past to allow users to use its flexible
graphics programming structures and techniques, which were, frankly, dense and intimidating to
use before then. We shall use the example of a Video Kiosk program to understand how this
toolbox, named “GDI+”, functions, and in doing so learn how to apply these tools in making
unique and creative graphical interfaces of our own, as well as simply using them effectively in
more straightforward projects.
We will cover the following sub-topics:
Introduction to creating Custom Controls.
Making a Control Library.
The ControlPaint class and its implementation in customizing controls.
Virtual Methods.
Overriding Events via Controls.
Exception Handling and caching Exception Flags.
COM Interop and how to use it.
Designing and Implementing Interfaces.
TODO lists.
TimeSpan and MessageBox Classes
An Introduction to GDI+
There has always been an exceptionally robust and capable graphics programming toolkit
available in Windows, referred to as “GDI”, though as we have mentioned it has often been held
back by the technical investment required to learn how to use it effectively. Specifically, GDI
consists of a group of unorganized structures and subroutines and uses API methods that do not
very simply fall in line with each other. In other words, GDI is implemented onto a “canvas”
procedurally.
In contrast, GDI+ is an object-oriented library of graphical tools that encapsulates all of the
above into one structure, i.e. it is an ordered, categorized version of GDI. This lets us peruse one
cleanly divided section of tools at a time, instead of spending half our time diving into a jumble
of structures to find one that we need.
Let’s learn about how GDI has been sorted into GDI+, and the resulting types, classes, and
namespaces that it is made of.
GDI+ Namespaces
The GDI+ Classes are stored in System.Drawing.dll , and are further divided using various
namespaces:
System.Drawing
System.Drawing.Design
System.Drawing.Drawing2D
System.Drawing.Imaging
System.Drawing.Printing
System.Drawing.Text
Combined, these broadly cover the three foci of graphics programming: typography (drawing
text using different glyphs, fonts, sizes, etc.), imaging (non-trivial graphical objects, such as
images, photographs, bitmaps, etc.), and 2D vector graphics (comparatively trivial graphical
objects, such as basic shapes, lines, and curves).
This defines a class CacheGraphics that inherits information from Form , and creates a new
Graphics object, storing it in the graphics variable. This does not work because GDI+ is
stateless. Any changes in the DC (which is contained in the Graphics object) will not be
transferred over into the graphics variable as it is only displaying a graphics according to the
information it has been given - it has stored none of said data. Thus, please do not try to create a
Graphics object directly using new, nor store an object of this sort in some field.
Instead, use CreateGraphics to make a new Graphics object to work on every time you need one
(alternatively, get the Graphics object argument from an event handler). Creating a Graphics
object is much more complex that simply calling for a new one, and using this predefined
method ensures that an object is initialized smoothly every time. You will have to provide it all
the state data it needs every time a new graphics operation is called for.
Let’s now look at an example of how to make a graphical interface using GDI+: The
PlayControl:
PlayControl
The PlayControl is a simple example of how to integrate graphics with functionality. A few
things are going on, on the surface level: rounded shapes and buttons, gradients and colors,
images contained in the button spaces, the VideoKiosk trademark logo, the slider on the top of
the interface, etc. As one might expect, the buttons respond to Click events, causing a Click
event handler to be called into function that passes its output to run the requisite code block.
Two things contribute to the reusable design of these graphical controls: one, controls are
implemented separately by the button, and two, the graphical design does not actually do
anything - it only serves to call a function using an IPlayer interface (which will be discussed
later). For example, pressing Play plays something by passing the respective command of the
PlayControl, on the condition that the IPlayer interface is used. Classes allow repeatability of
individual controls and the interface allows us to reuse the entire component. This interface and
its subroutines is described below.
using System;
namespace
VideoKiosk
{
public interface
IPlayer
{
void Close();
void Play();
void Pause();
void Stop();
void FastForward();
void FastReverse();
void VolumeUp();
void VolumeDown();
bool Open();
double Duration();
bool Mute();
void Mute(bool
state);
double Elapsed();
}
}
Owing to this sizeable list of functions, we can conclude that the IPlayer interface can be used to
emulate many modern devices on one computer instead.
Form1.cs , the main form in the VideoKiosk, is used to implement the interface, i.e. all functions
named in the interface are handled by this form. Therefore, we can call Form1 as a player using
PlayControl. To do so, we pass a reference to the PlayControl, contained within its constructor,
to the form as follows:
The PlayControl instances themselves associate and keep track of players. Its constructor is as
follows:
Since PlayControl is dependent on Form1, the PlayControl closes when Form1 does. The above
constructor shows how to call for the default constructor, which is the PlayControl method itself,
and takes no arguments. It must call this constructor since this is the function to initialize the
component. Without doing so, the control objects we wanted to create will not be created, and
the form will not work correctly.
This default constructor is called by this() ,and the subsequent player controls are cached in the
this.player variable field. This has now created a player that we can control using PlayControl.
Let’s look at how, for example, the play functionality is handled when we press the play button.
To begin with, the function player.Play() is called, which runs code in Form1. Form1 contains
the following in our example. This can be different for other sets of interfaces:
void IPlayer.Play()
{
axMediaPlayer1.Play();
}
A more nuanced and practical implementation of a play functionality (as shown in this example
code for VideoKiosk’s play command) would involve things such as event invocation and logic
checks:
Generally, it is a good habit not to write code into an event handler itself, instead placing a call to
a method, Play , and using PlayControl’s current context to determine what to do. It uses a
sentinel structure (we may also alternate towards using if-else or other conditional block
statements) to make sure that PlayerState is not null. For exception handling, this method is used
again, ensuring that nothing wrong happens to the player.
If the call (player.Play ) succeeds, PlayerState is updated and the player performs an action.
However, if it does not (for example, in the case of there not being a media file to play) the
Catch block (or else conditional, etc.) is called which runs a PlayError method and stops the
PlayerState. PlayError displays a message box, which you can edit using previously discussed
procedures.
Control Constructors
A constructor serves to initialize any objects that a class requires. A control constructor serves
the same purpose. Defining a constructor can be ignored in situations where new members do not
require initialization, or no particular method is required to be performed during initialization.
Constructors are usually public, have no return type, and have the same name as their class. For
our RoundButton class we do not need to have a constructor since we do not need any special
form of initialization.
Constructors can be overloaded (i.e. multiples of the same name can be defined and have
different functionalities, inputs, and outputs), and calls to the constructors are resolved
depending on what types of data are given as arguments.
A good idea is to use the constructor to call an initializer method instead of stuffing it full of
code. For example, Form1 uses the InitializeComponent method using its constructor, since it
has multiple controls that need to be initialized.
Destructor
To cover our bases, we’ll describe what a destructor is. It serves to remove and delete cached
data after its use is complete. We won’t often see it as compared to Dispose, but this is what it
looks like:
~RoundButton()
{
}
The former utilizes our method, whereas the latter uses basic statements to achieve the same
purpose and is clearer to understand. The IL code is different between the two because C#
doesn’t allow for typed arrays, and the Boolean must be converted to an integer first before it
will work to index the array.
Also, for very simple conditionals exists the ternary operator ( ? : ). It evaluates a variable as a
Boolean - if true, the first option applies, and if false, the second instead. This produces the least
amount of IL code, but it is difficult to use for multiple, complex conditionals (one might use
case instead).
You can use any of these methods as you please, and since the method is well-named, you can
code the routine as densely as you like. To summarize, keep the following in mind when
choosing a method:
Array indexing produces concise and specific code.
If-else statements are simple for a few conditions, but can get difficult to decipher
when nesting goes too deep and conditions get too many.
Case statements allow you to order multiple choices.
The ternary operator is a short and sweet method for simple binary choices.
A note about colors: a list of colors with their names is stored in the Color structure, which can
be called using the Getcolor method. We can also specify alpha blend (transparency of the
color), red, blue, and green hues (on a scale of 0 to 255, or base 8) to create a color.
Another note: we have used a Convert class in Getcolor. This class consists of methods to
convert datatypes to a particular type, such as Convert.ToInt32 converting data to a 32-bit
integer. These can accept most datatypes due to them being overloaded, as we have explained
previously. When it isn’t able to, an InvalidCastException is called.
Using Graphics Objects
A Graphics object in GDI+ is like a canvas, and multiple iterations of the object are required to
paint on it. To create a custom drawing, you’ll need to start by creating a Graphics object by
either using a CreateGraphics method from something that has a canvas, such as Windows
Forms, or as a property of the PaintEventArgs argument passed to the Paint event handler, or
other methods. Once you’ve created an instance of the object, you can use the class methods to
create your desired graphic. Take care not to cache this object nor use it in recursive methods
where a previous one is called since these objects are stateless and remember nothing. We’ll
show you how to request a Graphics object from the Paint event handler, and every time a Paint
operation is performed, below.
Paint Event Handler
This handler receives two input arguments:
An object.
A PaintEventArgs instance.
This handler is used most commonly in cases where one wants to create their own drawing. For
now, let us concern ourselves with only two methods, which are directly implemented onto the
PlayControl interface.
The Refactored methods in the code above describe their functionality. Then, to create a nice,
rounded shape, we add the first statement to use PlayControl in such a manner (we could not
have created this shape otherwise). Lastly, to add the trademark “VK”, we write the second
statement. The following code elaborates on these functions:
OutlineControl modifies the Graphics object to set the SmoothingMode parameter to AntiAlias ,
which blends multiple pixels in a polygon to smoothen it out. The new, smoothened shape is then
returned using GetPoints .
DrawTrademark creates shadows and an inset effect by applying multiple layers of text. These
text layers are created using a method called DrawShadowText that offsets the text to a side or
throughout. The inset effect is created by writing that text offset by -1 and inputting a brighter
color.
Overloading OnPaint
One can either create multiple custom effects on a form every time the graphic is instanced or
create custom controls to handle all of that. To do so, we would need to overload the OnPaint
method. This is the method we use to remake a control (such as our RoundButton) every time it
is painted.
In our PlayControl code listing, we notice that OnPaint is not an event handler, as this method is
a part of the class that is being used to create a custom painting. We do not need to give it an
event flag, but we need to give it a PaintEventArgs object, with the Graphic object we’re using.
If you want a default drawing method followed, you can use an inherited OnPaint method instead
that will also call the event handler. After we’ve made the base drawing, we will insert this code
that makes our custom painting, as we’ve shown in the PlayControl listing by using DrawButton
and DrawGraphic . We’ll go over GDI+ tools to do this soon.
Invalidating a Control
We use the Invalidate method to change a control’s graphics. It calls OnPaint, causing a Paint
event, and forces the control to be repainted. In the PlayControl listing, this is shown on line 72,
in the HasOutline subroutine.
When the button is clicked, the RoundButton control calls the OnMouseDown method (in this
case, we use the base class’ OnMouseDown method, which allows the user to intercept that
event), causing the down field to be set to True to invalidate and update the button. This calls
OnPaint to repaint the control; the base.OnPaint method first, then the custom method. When
down is True (I.e. the button is pushed in), the DrawDownGraphic method creates a matrix
object. This object is scaled and fed to the Graphics object via graphics.Transform to create the
requisite effect. Using transforms is something of an art and you’ll need a good eye, practice, and
retries to get the perfect fit for you.
This code creates a GraphicsPath object Path . This object receives points using GetPoints, and
is sent into Region to define a region to clip in order to create a form. This is a simple example to
help you understand its basic functionality in the context of our PlayControl, but is fairly lacking
on its own. We will elaborate on this shaped form below.
This block of code also changes the background color in the Form Load event. We initialize a
new GraphicsPath object and provide it a string and some information on the font it is to use.
This object is used to create a Region, which is assigned to the form’s Region field.
We have used LinearGradientBrush to paint RountButton and have also added a condition to use
different gradients depending on the state of the down field.
The following listing shows how we can use LinearGradientBrush methods RotateTransform and
SetTriangularShape .
1: using System;
2: using System.Drawing;
3: using System.Drawing.Drawing2D;
4: using System.Collections;
5: using System.ComponentModel;
6: using System.Windows.Forms;
7: using System.Data;
8:
9: namespace GradientBrushDemo
10: {
11: public class Form1 : System.Windows.Forms.Form
12: {
13:
14: [ Chopped out code that was generated by the forms
designer]
15: private System.Windows.Forms.Timer timer1;
16:
17: private float angle = 0;
18:
19: private LinearGradientBrush GetBrush()
20: {
21: return new LinearGradientBrush(
22: new Rectangle( 20, 20, 200, 100),
23: Color.Orange,
24: Color.Yellow,
25: 0.0F,
26: true);
27: }
28:
29: private void Rotate( Graphics graphics,
30: LinearGradientBrush brush )
31: {
32: brush.RotateTransform(angle);
33: brush.SetBlendTriangularShape(.5F);
34: graphics.FillEllipse(brush, brush.Rectangle);
35: }
36:
37: private void Rotate(Graphics graphics)
38: {
39: angle += 5 % 360;
40: Rotate(graphics, GetBrush());
41: }
42:
43: private void timer1_Tick(object sender,
System.EventArgs e)
44: {
45: Rotate(CreateGraphics());
46: }
47:
48: private void Form1_Paint(object sender,
49: System.Windows.Forms.PaintEventArgs e)
50: {
51: Rotate(e.Graphics);
52: }
53: }
54: }
Notice how we’ve used a Timer control to recreate an ellipse at regular intervals. We have used
Yellow and Orange as the two gradient colors. Every time we use the Rotate method, we
increment the floating-point value by five, which is kept in check using a modulo operator.
RotateTransform rotates the brush and SetBlendTriangularShape creates a triangular-shaped
gradient, the three outer points transitioning from one color to the other as it approaches the
center. Finally, we use FillEllipse to fill an ellipse using this brush.
Pens
Pens work similarly to Brushes; you can either create an instance of one to use or call one
explicitly from the Pens class. The code below creates a Pen object, initializing it using a
LinearGradientBrush, and uses it to draw an ellipse.
LinearGradientBrush brush =
new LinearGradientBrush(new Rectangle(0, 0, 2, 2),
Color.White, Color.Green,
LinearGradientMode.ForwardDiagonal);
Pen p = new Pen(brush, 10F);
e.Graphics.DrawEllipse( p, 5, 5, 100, 200);
Tracker Control
We recall that we used the Control class to create our RoundButton class object. We could’ve
improved by using a ButtonBase class, since its functionality and structures are similar and thus
easier to modify. You should always consider what base class to use, so that the modification of
your inherited structure is much easier to achieve. You can also create a Control class from
scratch, which is described later in the book. Sometimes neither of these work and you will need
to create an inherited class with a base that is tiered higher on the control hierarchy, such as
System.Windows.Forms.Control .
public Tracker()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor,
true);
}
ControlPaint
ControlPaint is a GDI+ class that contains methods to draw 3D shapes such as buttons or sliders.
This class is defined in the Systems.Windows.Forms and consists of methods for designing
buttons, checkboxes, menu glyphs, radio buttons, size grips, etc. We’ll use ControlPaint to make
the visual interface of the Tracker.
Drawing a 3D Border
We want a 3D border for our Tracker. The Tracker class has a DrawBar method that draws a bar
groove for the Progress Indicator to move along. This method takes a Graphics object as an
argument and calls a DrawBorder3D method to operate on it.
This method is static, and thus requires no special ControlPaint object to be created for it.
Boundaries for the region are specified using GetX , GetY , GetWidth , and GetHeight methods
relative to the tracker’s size. The last two arguments are enumerated values, selected from a list
of available members according to our design considerations. This helps create a visual style that
indicates movement along the line, and thus we implement the etcborder-style along all sides of
the border.
Drawing a Button Control
We can go about creating a button for the Tracker in multiple ways. One way involves scaling an
image that is inserted into the control according to the size of the tracker. For instance, let this
image be the shape of a button. To draw this, the control uses Tracker.drawTracker to call
ControlPaint.DrawButton which draws the indicator.
The vertical offset is (Height – 8)/2, which puts the button squarely along the line. Tracking the
horizontal position is more complex, and we will use TrackPosition to achieve this.
ButtonState.Normal draws the button in an unpushed state.
Graphics.DrawImage
The buttons included in the PlayControl are of various types, differing most visibly by the image.
Thus, instead of creating unique classes for each button, we can make one class with a subroutine
to change what image it needs to display. The following code describes an ImageButton object,
which is a derivative of RoundButton.
Of key importance is how to alter the image so that it fits into the button’s display. For example,
some parts of an image are perhaps unnecessary to display. To remove these parts, you can
screen them out by defining an ImageAttributes object which defines what colors need to be
removed. Also, notice how overloaded DrawImage is so as to account for a variety of input
arguments.
ImageButton, now, uses the ImageAttributes object we created to screen our desired color
(white, in this case) and removes it. If we want only to remove a specific part of the image, make
that part match the same color as given to the ImageAttributes method.
Secondary Topics
We’ve given you a fairly solid overview of how VideoKiosk.sln works but do keep in mind that
the listing for this structure, which includes Control.dll as well, is well over a few hundred lines
of code. These would allow you to simplify your operation of making all of your control buttons
from one base RoundButton object, but we wanted to show you how to use and appreciate GDI+.
However, it does use a few structures from .NET to round out its functionality, which is
tangential to our topic. We’ll discuss them here for your perusal.
This method also knows how to convert seconds to other larger units of time. Seconds are
converted to minutes and hours automatically. GetMask provides a formatting string to control
the appearance of TimeSpan, which is then used to update the clock. We’ll discuss this
formatting string soon.
Using TimeSpan to Tell Time
TimeSpan can measure time differences to an accuracy of 100 nanoseconds. This is a ”tick” of
the TimeSpan, like the tick of any other clock. TimeSpan can be represented as either a positive
or negative span of time that can measure out to days. The string that TimeSpan stores its time in
is d:hh:mm:ss.ff , where ff refers to fractions of a second. If we needed this string we could use
TimeSpan.ToString() to get time in that format. Performing arithmetic on DateTime values also
yields a string like that.
Formatting Strings
We choose not to use TimeSpan.ToString() and instead do it manually for a more educational
view into the string's inner workings.Format and formatting masks.
GetMask provides you with a formatting mask , which serves to receive data values from the
string. This mask is “{0}:{1,2:0#}: {2,2:0#}”: values in the bracket are format characters that
can be modified, and everything else is literals. The first value represents the zero-based
argument to be changed, and any value after the comma represents the size of the argument. The
third value represents the number and adds a zero to the number if there’s space for it (in the case
of the number being too short). For example, {1,2:0#} represents the first replaceable parameter,
length 2, and currently filled with 0.
Tooltip Control
Windows Forms contains a ToolTip structure. This structure is added to the component tray of a
program, rather than the main form, which causes the Form’s controls to have the ToolTip
property added: this allows you to display a tooltip textbox when the mouse hovers over a
control. They are invisible components and do not show up during runtime automatically. Using
it seems unintuitive at first, and Windows Forms does not seem to support it at a cursory glance,
but it is as simple as adding it to the Component Tray.
Adding Controls to a Toolbox
We create a custom control to add a set of functionalities to a container. Adding a control
automatically adds it to the Windows Forms tab of a toolbox.
Adding controls to a Toolbox requires you to create a Control Class library, into which you will
add the methods you need. You can then access the Customise Toolbox option from the Toolbox
context menu and add this library to the list you want to display in the Toolbox. This will be
expounded upon in later sections of the book.
Catching and Handling Exceptions
We’ve learned how to work with exception flags using the resource protection block and the try-
finally structure. VideoKiosk.sln used the try-catch structure instead. The Try block is the place
where you place your main code to run, and the Catch block is where you add exception-
handling code. If an exception is raised in Try, the Catch block is called. The basic syntax for
this is:
try
{
// code to try
}
catch
{// code to run if an error
occurs
}
You can use multiple Catch blocks for multiple exceptions that each work for a particular class
of exceptions. The following is an example of how to do so - in the method, SetMaximum is a
function to catch an exception called OverflowMaximum the input integer is larger than 32 bits.
keyword we have defined. To use them, place them immediately after your double forward-slash
comment token ( // ). This places the comments in a task list. We can look through this task list
by going through View > Show Tasks > All, or View > Show Tasks > Comment, in the Visual
Studio environment. To make custom tokens, define them in the Options list or the Environment
> Task List page:
The following code demonstrates an update to the previous code for the ImageButton class,
where we remembered to edit it using a comment. We’ll add the ability to delete the Image
property in the class, which is done by assigning it a DefaultValueAttribute .
The problem is resolved in line 52 of the above code. After this is done, remember to remove the
TODO token from your code.
A tip for using comments is to add custom tokens to classify what kind of problem something is,
and how it should be handled.
The Process Class
The Process Class, introduced in a previous section of the book, is used to actually receive an
impetus for the rest of the code to run. Process.Start is a static method attached to the Click
event handler for the leftmost ImageButton control on the PlayControl interface.
COM Interop
COM Interop (for interoperability) is a concept in .NET languages that uses COM libraries and
controls in .NET environments since .NET uses Reflection and metadata in its assemblies to
achieve the same goal. These concepts were explained in a previous section as well if you would
like to review them.
Let's take the example of the ActiveX Media Player from VideoKiosk.sln. This is a COM-based
control, and to use it we need to import these controls to our .NET toolbox by selecting
Customize Toolbox from the Toolbox menu. This will import the type library for that COM
control, and allows their usage in a .NET environment. This, of course, comes with the caveat
that you will be using outdated COM structures, and you also will need to create an installer
program to register these commands and methods.
To conclude the discussion we made so far in this chapter, GDI+ is an improvement and a
streamlining of Windows’ powerful GDI toolkit, making it much easier and more lenient to
handle due to the advent of .NET and the addition of new methods and structures. GDI+ is used
for imaging, typography, and vector-based graphics. The structures GDI+ uses are stateless and
require constant streams of their information. Use CreateGraphics to create a Graphics object, or
take the object received by Paint event handlers.
Chapter Four
Personalizing the Visual Studio .NET Framework Environment
There has been considerable investment and research made towards code automation capabilities
for Visual Studio by Microsoft. This serves to provide quality-of-life changes to the way
programmers can code things. We are given the capability to replace tedious and monotonous
processes with automated Wizards, macros, and templates that we can create and use ourselves.
These macros are extremely flexible owing to an extensibility model that lets you customize
every detail of Visual Basic .NET. This chapter will not go over every detail that you can
customize, but rather how to create objects such as Wizards and macros yourself, providing you
with practical information that you can apply and develop yourself.
In this chapter, we will create project templates. Specific topics we will cover are:
Making a Wizard
A Wizard , colloquially, refers to a series of dialogues that are fed information to create a result.
These structures have become immensely popular thanks to Windows, and the above definition
is a result of that fame. Another more accurate definition is that a Wizard is a series of linear
subprograms, as compared to spatial-based programming that existed at the time. The advantage
that the linear model offers is that it reduces the accessibility of the program at a given step,
which is beneficial in cases such as outcome-based tasks.
An esoteric definition for programmers is that a Wizard is an application or subprogram that
breaks down a task or goal into multiple steps for the user to follow and complete, which is
accomplished using IDTWizard. The user’ interaction with the Wizard is very easy and they only
need to click a Next button to continue most of the time. Developers have a harder time selecting
a Wizard, since all of the back-end needs to be reformulated in order to compress the commands
into one button press. However, it’s actually quite simple to use IDTWizard to create a Wizard,
and the artistic vision of the programmer can be implemented into the console.
The following piece of code is a basic introduction to using IDTWizard to make a Wizard. A
more advanced example is also provided later in this chapter.
using System;
using EnvDTE;
using System.Windows.Forms;
namespace HelloWizard
{
public class HelloWizard : IDTWizard
{
public void Execute(object Application,
int hwndOwner, ref object[] ContextParams,
ref object[] CustomParams, ref WizardResult
retval)
{
MessageBox.Show("Hello Wizard");
retval =
EnvDTE.WizardResult.WizardResultSuccess;
}
}
As you can see, a functional definition of a Wizard is a class that implements the IDTWizard
interface, as defined in EnvDTE. There is only one method defined in IDTWizard: execute.
Putting in the rest is up to the programmer, as is testing if it works.
A Wizard Project
Wizards are basically a collection of classes, so to make one we’ll need to create a class library.
To start making a Class Library Project, go to the New Project dialog, select the Class Library
template, name your project, and press OK. You’re now on your way to making your own
Wizard.
Using IDTWizard
To use IDTWizard to make your Wizard you will need to reference the design-time environment,
i.e. Visual Studio .NET’s extensibility model. To do so, add a reference to the envdte.dll
assembly to the project’s references and refer to the library with the keyword.
There is only one function in IDTWizard, Execute , and it must be provided an array of context,
an array of custom parameters for it to use, an owner handle, and a return value that uses a pass-
by reference modifier.
Pass-By Referencing
We need to create a method that returns a value of a datatype other than void. The parameter that
this method returns can also be given the keyword ref to allow it to return multiple values, by
virtue of them being able to be affected by the caller. Equivalents to ref in other languages
include passing pointers in C++, ByRef in VisualBasic .NET, and var in Delphi. An example
code will describe this method below.
Testing the Wizard
After adding your functionality to the Wizard, you can run it to find out if it works. The
Singleton object DTE contains a method called LaunchWizard , which does exactly that
(specifics are given later in the chapter). The next listing of code is a macro for testing the
HelloWorld Wizard we made earlier, and the one after that is an example of stuff that you can
put in a Wizard.
Imports System
Imports EnvDTE
Imports System.Diagnostics
Public Module Module1
Public Sub Test()
Const Path As String = _
"C:\Temp\HelloWizard.vsz"
Debug.WriteLine("This is running!")
Dim ContextParams(1) As Object
ContextParams(0) = Nothing
DTE.LaunchWizard(Path,
ContextParams)
End Sub
End Module
This macro can be found in Macro IDE: go to Tools > Macros > Macros IDE to open the menu.
Now we need to create a Wizard launch file. This launch file has the extension .vsz and has the
same name as the Wizard’s class library.
VSWIZARD 7.0
Wizard=HelloWizard.HelloWizard
Param=<Nothing>
Place this code in a file named HelloWizard.vsz, and place the file in the same directory as the
HelloWizard.dll. HelloWizard.dll has been registered using regasm.exe, a Visual Studio .NET
utility. The process of registering your Wizards will be explored later in the chapter.
This process is, admittedly, quite tedious, but this is a generic and therefore extensible list, which
can be used to create any project template that you would like to. The following sections will
expand upon this checklist, along with how to complete the task that each asks of you, and a
further description of the process. We will also follow the checklist in order.
Creating a New Template from a Pre-Existing Template
Project templates are the methods represented by the icons in the New Project dialog. You can
also create an entire template from scratch as a text file, but this is easier. Take care to consider
what project template you will base yours off as different versions of Visual Studio have
different templates.
To create a template, select one close to yours, which in our case is the Class Library template.
To access this template, go to “…Files\Microsoft Visual Studio .NET\VC#\
VC#Wizards”. Here, the Class Library is represented by CSharpDLLWiz. Follow the below
steps in order to create a new template using this one.
Copy the library folder to the same directory, which will name it “Copy of
CSharpDLLWiz” by default.
Name it whatever you want. We recommend naming this folder
CSharpDLLWizWiz, keeping the convention
These folders have a Scripts and Templates subdirectory that contains a language identifier. For
English users, this identifier is most likely in 1033. The scripts\1033 folder contains the
template’s default.js file, which we will learn to modify later. The templates\1033 folder contains
actual code files that the engine will use to create a template. We will discuss how this works just
after this section. Remember that right now these are still just the same files from the Class
Library template.
Your folder should start to look something like this:
using System;
using EnvDTE;
namespace [!output SAFE_NAMESPACE_NAME]
{
/// <summary>
/// Summary description for [!output
SAFE_CLASS_NAME].
/// </summary>
public class [!output SAFE_CLASS_NAME] :
IDTWizard
{
public [!output SAFE_CLASS_NAME]()
{
//
// TODO: Add constructor logic here
//
}
public void Execute(object Application, int hwndOwner,
ref object[] ContextParams,
ref object[] CustomParams, ref wizardResult retval)
{
//
// TODO: Add your custom code here
//
retval = EnvDTE.wizardResult.wizardResultSuccess;
}
}
}
Notice how this is very similar to our original HelloWizard code, with the addition of
SAFE_CLASS_NAME replaceable tokens. Again, you don’t need to change any files in this
folder, but you can inspect them to see what they do and modify them if you want to.
Modifying default.js
default.js is stored in Scripts\1033. To modify it for our template, we need to make one small but
important modification to it that allows our Wizard projects to reference envdte.dll. We need to
coordinate this with common.js as well, which is described in the next section. For now, let’s see
how we will modify default.js:
The template wizard is designed to use external JScript functions. There are four of them
mentioned here: OnFinish , GetcSharpTargetName , DoOpenFile , and SetFileProperties . These
are used exclusively by the template wizard to call for the Wizard Library.
SetFileProperties sets up a flag to mention that the .cs files contain code.
DoOpenFile opens the class module file in Visual Studio .NET.
GetcSharpTargetName changes the name of the file. We use it to change file1.cs’
name to class1.cs instead.
OnFinish completes the substitutions for the methods and parameters in the file,
and ties up the package.
Description:
oProj: Project object
********************************************************/
function AddReferencesForWizard(oProj)
{
var refmanager = GetcSharpReferenceManager(oProj);
var bExpanded = IsReferencesNodeExpanded(oProj)
refmanager.Add("System");
refmanager.Add("System.Data");
refmanager.Add("System.XML");
refmanager.Add("envdte");
if(!bExpanded)
CollapseReferencesNode(oProj);
}
We made this using the AddReferenceForClass method, adding a call to the refmanager to refer
to envdte.dll. We can do this because the Class Library structure is already very similar to ours.
If we’re making a template from scratch, we would need to create other methods and classes.
Now all that’s left is to create a VSDir file and the Wizard Launcher file.
The Wizard Launch File
We’ve already discussed how to create a Wizard using IDTWizard in a previous section titled
“Creating a Custom Wizard”. However, we do not need to create a Wizard from scratch. We’ll
modify the Class Library template’s Wizard and use that. We will only be telling the New
Project dialog the Wizard it needs to select. The Wizard Launch files for all Project Templates
are stored at the directory “…\Microsoft Visual Studio .NET\VC#\CSharpProjects”. The Wizard
Launch file for the Class Library is stored in CSharpDLL.vsz . Copy this file, rename it to
something like CSharpDLLWiz.vsz , and modify the code within to refer to our template, as
follows:
VSWIZARD 7.0
Wizard=VsWizard.VsWizardEngine
Param="WIZARD_NAME =
CSharpDLLWizWiz"
Param="WIZARD_UI = FALSE"
Param="PROJECT_TYPE = CSPROJ"
The only change we made to the original file is to change the Wizard to refer to our template’s
wizard. The other parameters are just conditional values. Now all that’s left is to create VSDir
and test our template.
Creating a VSDir File
These files define what information is received by the New Project and Add Item dialogs and
how items in those lists are displayed. They require two things - an icon and a name. Specify the
connection between these two things and the template you want them to refer to. The listing for
VSDir is as below, written in a single line - we will explain how this works after:
CSharpDLLWiz.vsz|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|Wizard
Library|
20|#2323|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|4547|
|WizardLibrary
This one line contains the existing project template’s items. VSDir files are stored in “…
\Microsoft Visual Studio .NET\VC#\CShaprProjects\CSharpEx.vsdir” and this folder will also
contain your Wizard Launch file.
This one line is divided into fields by “pipes” (the “ | ” symbol). The following table breaks these
fields down in order of appearance, and describes what they do.
Relative Path Name CSharpDLLWiz.vsz Specifies the wizard launch file using a
relative path. Store the .vsz file in the same
directory as the .vsdir file.
{FAE04EC1-301F-11d3- CLSID package A GUID representing a resource DLL. This
BF4B-00C04F79EFBC} particular GUID refers to something named
the C Sharp Editor Factory.
Wizard Library Localized name This is the template's localized name and the
name that will appear in the New Project
dialog.
20 Sort priority Determines the order in which elements are
listed. A sort priority of 1 is the highest.
#2323 Description A string or resource identifier containing a
localized text description of the template.
{FAE04EC1-301F-11d3- DLLPath or CLSID package Contains a GUID reference to an EXE or
BF4B-00C04F79EFBC} DLL resource that contains icons for the
template.
4547 Icon resource ID Indicates which icon to use from the resource
file referred to from the previous entry.
<blank> Flags Bitwise flags, not used by our template. You
can refer to the Visual Studio .NET help for
VSDir files for individual flag values.
WizardLibrary Suggested base name Specifies the default name for the template.
Our entry represents a project, therefore, the
root name for Wizard Library projects will be
WizardLibrary. The first new project will be
WizardLibrary1, and so on.
This template is used to create the following entry in the New Project dialog box:
Now that everything is done, lets test our template by creating a new project. Go to File > New >
Project, click on the Wizard Library icon, and press OK. You should now have a new Class
Library project with an assemblyinfo.cs file and a file named WizardLibrary1.cs, which should
contain a basic execution of IDTWizard. Do double check that a reference to envdte.dll exists.
A final note for this section regarding the project’s template is that it’s a combination of shared
files from across the base class and the environment. An important one of these is
DefaultDLL.csproj file, which is located in “…\Microsoft Visual Studio .NET\VC#\VC#Wizards
folder. All DLL-based projects refer to this template. Also, most of the process of creating a
template is copy and pasting things, rather than creating things from scratch. Make a template if
you are going to use a custom project structure often to simplify tedious tasks and streamline
your process.
Now that all of this works, let’s use these to make something that automates tasks for you.
Writing a Macro
We now already have a basic understanding of how to create, write, and test wizards, which will
serve us well in writing macros as well, alongside things such as C# programming and Windows
Forms interfacing. Let’s continue with how to write a macro.
Macro support is a part of Visual Studio .NET’s extensibility model, alongside but separate from
Macros IDE. Macros are written using Visual Basic .NET. Macros IDE is a project-centric
environment, and the macro files created are stored with .vsmacro extensions, though Visual
Basic code can also be communicated to it.
To start, open Macros IDE from Tools > Macros > Macros IDE. Using this is similar to Visual
Studio .NET. In this new environment, select the Project Manager from the View menu. To
create a new macro, select an existing module or create a new one (a module is a sourcecode
file). Add a simple subroutine (read: method) to it and see if it works by starting a debug process
from Debug > Start. Here’s an example of a macro which simply produces a message box that
says “Hello World!”:
Sub HelloWorld()
MsgBox("Hello
World!")
End Sub
Let’s move on to a more practical example of a macro that adds a new class to an existing
project, similar to how we will reconstruct TypedCollectionWizard later. The following macro
does exactly that: it adds a new class file to an active project’s directory, and the second (empty)
entry is where the name of the new class would go. By default, an appropriate name is produced
by the method itself:
Sub TestNewFile()
DTE.ItemOperations.AddNewItem(
_
"Local Project Items\Class", "")
End Sub
Notice the DTE namespace keyword. The following section is devoted to giving a brief overview
of this keyword, referring to the design-time environment.
The Common Environment Model
A DTE is a design-time environment object, referred to by internal documentation as a Common
Environment Model, or the automation model, or the extensibility model. We will continue to
refer to it as a DTE. It is the root of a project, representing an object model allowing access to the
capabilities of Visual Studio .NET. DTE uses interfaces to create an object-oriented accessibility
within the Visual Studio .NET environment, which is, in effect, a method for automation. The
documentation for this model is very large, and perusal is at one’s own risk.
For our current concern, we’ll only use a small section of that manual to apply DTE for macros
and C# code, which should serve to introduce you to the core concepts of using it. A good way to
think about DTE is as a mask that interacts with Visual Studio .NET, including menus,
documents, macros, etc.
creates a C# file, by calling for a new one and obtaining a reference to the
ProjectItem for it.
adds a default namespace, and formats a namespace element.
inserts text into that file, by assigning edit points. Text can be added here either
manually or using Add methods.
This file is added to the current project, but it cannot create a project on its own. Running this
code results in the following:
namespace
TestWizardOuput
{
5/9/2002 5:12:23 PM
}
Code Generator
You can create a code generator by centering it around structures that exist in all instances of
your code. Add string-based inputs to work with these structures and add dynamic functionality
to it. For example, the templates’ code generator Wizard is written as follows:
1: using System;
2:
3: namespace TypedCollectionWizard
4: {
5: /// <summary>
6: /// Summary description for Wizard.
7: /// </summary>
8: public class Wizard
9: {
10: /// <summary>
11: /// Parameter 0 is the class name; parameter 1 is the type
name;
12: /// parameter 2 is the optional setter; parameter 3 is the
comment.
13: /// </summary>
14: private const string template =
15: " // Code generator by [email protected]\r\n" +
16: " {3}\r\n" +
17: " public class {0} : System.Collections.CollectionBase\r\n"
+
18: " {{\r\n" +
19: " public {1} this[int index]\r\n" +
20: " {{\r\n" +
21: " get{{ return ({1})InnerList[index]; }}\r\n" +
22: " {2}" +
23: " }}\r\n\r\n" +
24: " public int Add({1} value)\r\n" +
25: " {{\r\n" +
26: " return InnerList.Add(value);\r\n" +
27: " }}\r\n" +
28: " }}\r\n";
29:
30: private const string setter =
31: "set{ InnerList[index] = value; }\r\n";
32:
33: private string name;
34: private string typeName;
35: private bool hasGetter = true;
36: private bool hasSetter = true;
37: private string comment;
38:
39: public Wizard(string name, string typeName, bool
hasGetter,
40: bool hasSetter, string comment)
41: {
42: this.name = name;
43: this.typeName = typeName;
44: this.hasGetter = hasGetter;
45: this.hasSetter = hasSetter;
46: this.comment = comment;
47: }
48:
49: private string GetSetter()
50: {
51: return hasSetter ? setter : "\r\n";
52: }
53:
54: private string Getcode()
55: {
56: return
57: string.Format(template, name, typeName,
58: GetSetter(), comment );
59: }
60:
61: public string GetTemplate
62: { get{ return template; } }
63:
64: public string Code
65: { get{ return Getcode(); }}
66:
67: }
68: }
This code is fairly straightforward, making a template that uses parameters that vary from class
to class, and using them when needed upon calling Getcode. More importantly, we can use this
standalone to test whether it works for the Wizard. This results in the following code, which is
syntactically correct and works as intended for the Wizard.
Any changes to the control of the Textbox only need to be referred in one place in the GUI code.
Another thing you can do is to validate field input in the UI as well as the class, using regular
alphanumeric expressions. The following code confirms this.
1: using System;
2: using System.IO;
3: using EnvDTE;
4: using System.Windows.Forms;
5:
6: namespace TypedCollectionWizard
7: {
8: /// <summary>
9: /// Summary description for Class1.
10: /// </summary>
11: public class CollectionWizard : IDTWizard
12: {
13: // Implements IDTWizard.Execute
14: public void Execute(object Application,
15: int hwndOwner, ref object[] ContextParams,
16: ref object[] CustomParams, ref wizardResult retval)
17: {
18:
19: string generatedCode = string.Empty;
20: if( FormWizard.Execute(ref generatedCode))
21: {
22: WriteCode((DTE)Application, generatedCode);
23: retval = EnvDTE.wizardResult.wizardResultSuccess;
24: }
25: else
26: {
27: retval = EnvDTE.wizardResult.wizardResultCancel;
28: }
29: }
30:
31: private void WriteCode(DTE dte, string
generatedCode)
32: {
33: try
34: {
35: DoWriteCode(dte, generatedCode);
36: }
37: catch(Exception e)
38: {
39: MessageBox.Show(e.Message, "Error Writing Code",
40: MessageBoxButtons.OK, MessageBoxIcon.Error);
41: }
42: }
43:
44:
45: private void DoWriteCode(DTE dte, string
generatedCode)
46: {
47: ProjectItem item = dte.ItemOperations.AddNewItem(
48: @"Local Project Items\Code File", "" );
49:
50: string defaultNamespace =
51: (string)item.ContainingProject.Properties.Item(
52: "DefaultNamespace").Value;
53:
54: CodeNamespace code =
55:
item.FileCodeModel.AddNamespace(defaultNamespace,
0);
56:
57: EditPoint editPoint = code.StartPoint.CreateEditPoint();
58: editPoint.LineDown(2);
59: editPoint.Insert(generatedCode);
60: }
61: }
62: }
This code completes using IDTWizard, displays the form, writes code using the code generator if
Execute is true using WriteCode, which manages error handling using a try-catch structure, and
generates a code file using DoWriteCode.
We’ve used DTE in this code by casting an Application parameter onto a DTE object, and using
that to generate source code.
This demonstrates the automation capabilities of Visual Studio .NET, and it is one of the reasons
it is so beloved by software programmers. Now to test the Wizard!
VSWIZARD 7.0
Wizard=TypedCollectionWizard.CollectionWizard
Param=<Nothing>
Let’s move on to a more complicated example. The following is the Wizard Launcher file for the
C# Indexer Wizard that works alongside the Wizard Engine. You can pass any kind of
parameters into the Wizard using this, such as the Wizard’s name and the Project type.
VSWIZARD 7.0
Wizard=VsWizard.VsWizardEngine
Param="WIZARD_NAME =
CSharpIndexerWiz"
Param="PROJECT_TYPE = CSPROJ"
Registering Wizards
The Wizard requires access to the Registry, but does not need to be a member of the Global
Assembly Cache (or GAC). To this end, we can register it using regasm as follows:
c:\winnt\Microsoft.NET\v1.0.3705\regasm
c:\temp\TypedCollectionWizard.dll
/codebase
This is the default path for the .NET framework. If there’s a different directory in place of
c:\temp , use that. /codebase stores these path in the registry using file:// . Again, the Wizard is
still a .NET structure, only accessing the registry. It is not a COM component. There will be an
explanation at the end of the chapter.
A quick note, the GAC is a cache for all the assemblies being used by the machine. A Wizard is
not a permanent part of that list, and thus it doesn’t need to be registered. The GAC is, in effect,
a giant folder that contains and catalogues assemblies for easy use. We recommend looking into
a .NET utility called GACutil.exe.
Testing the Wizard using a Macro
Let’s use our macro that we made at the beginning of the chapter to test our Wizard. Replace the
macro’s constPath variable with the address to the TypedCollectionWizard, and run it.
Running the Wizard from the Command Window
We can use our macro from the previous section to run our Wizard from the Command Window.
Select View > Other Windows > Command Window. We’ve created a test macro called
MyMacro, stored it in a module named Module1, and named the method inside
TestCollectionWizard. All of this combined, we call our Wizard with this line of code:
Macros.MyMacros.Module1.TestCollectionWizard
A list of commands will pop up when you type the word Macros, via Intellisense.
Secondary Topics
The chapter introduced into a wide variety of tools and concepts such as JScript, gacutil.exe,
regasm.exe, etc. These are structures with extensive documentation, and a more thorough
introduction to these concepts is in order:
Returning to JScript
We used a bit of JScript to implement our templates, which is done by calling an external
compiler. However, JScript is a completely different and just-as-fleshed-out language as
compared to Visual Basic .NET and C#. You’re likely to find code written in this language in
things such as clientside code for webpages and ACT (a testing automation application
developed by Microsoft). The following checklist describes how you may go about writing some
JScript .NET code.
Open NotePad.
Write print.(“Hello World!”) .
Save this file as HelloWorld.js, and remember its directory. Close the file.
Open the command prompt, and run the file by calling the compiler as follows:
c:\winnt\Microsoft.NET\Framework\V1.0.3705\jsc
Hello.js
regasm assemblyname
/codebase
regasm assemblyname
/unregister
1) regasm simply refers to the utility. assemblyname is the name of the assembly
containing the Wizard DLL. /codebase adds the code to the registry. It is technically
all that is required to make a complete call, though it does provide a warning to use a
strongly-worded name (by using sn.exe, for example) to avoid version problems.
2) Similar to the above, except it uses /unregister to unregister the Wizard from the
registry.
The wizard does not use COM. It is required to register the DLL into the registry to load it into
the Visual Studio .NET environment.
To read the registry assembly, do:
regasm assemblyname
/regfile:regfile
where assemblyname would refer instead to your assembly and the second regfile refers to a .reg
extension file.
Programming has come a long, long way from what it was ten years ago, and it continues to
grow and develop at an exponential pace. We’ve developed things such as exception handlers,
that have a contingency plan for pretty much every situation that we can imagine.
As we’ve mentioned, the field of programming is ballooning at an extremely rapid pace, and it’s
quickly becoming less and less probable that one person can know everything about
programming. Specialization is the norm now as it is simply impossible for someone to know
everything about everything. Just in this one chapter, we’ve touched on three massive languages
- Visual Basic .NET, JScript (or JavaScript), C# - and utility programs GACutil.exe and
regasm.exe. A programmer now only has a basic understanding of the underlying concepts but
needs to opt in to one of these fields. They can focus on game development, or web design, or
even more utilitarian application/software programming. Anything you can imagine.
Automation also is beginning to form a real concern to programmers (and humans as a whole),
based on the strength of modern computers and the speed at which they can grasp concepts given
a ruleset. In games requiring intellect and complex decision-making, such as chess, the Chinese
game Go, and DotA 2, programs that have used advanced automation to repeat processes and
develop optimal strategy have far overtaken the capability of humans. Programming can be left
to programs themselves, now.
Conclusion
We have now come to the end of our journey. Even though you might have felt C# to be a bit
difficult and at times, frustrating to understand, regardless you have increased your programming
knowledge. In the world of programming, experience is the best teacher you can ever find. While
we have tried our best to provide you with adequate explanations of concepts and advanced
topics, you might still feel that something was missing. If that’s the case, then you are on the
right track of learning. Anything that you feel is ambiguous, will serve as an impetus to a
specific topic for research which will expose you to even more things, causing a domino effect.
Every chapter in this book has tried to cover all of the aspects of C# programming to a certain
extent, however, it is out of the scope of this book to completely dominate every advanced
programming element of C#. Thus, it is important to provide the readers with the C#
programming’s most important central information, if not the complete package. It is highly
recommended that you research the aspects which confuse you, this will help clarify your
concepts at a level which would otherwise have not been possible.
In short, we have explored the fundamental principles of object-oriented programming in the first
chapter and learned how C# implements these principles through various functions. In the next
chapters, we discovered the extended functionalities in C# programming such as using the
‘Reflection’ function in the .NET framework to extract information from assemblies and use
them. Finally, we move on to truly advanced C# programming topics such as using ‘GDI+ ,’
working with Visual Studio .NET and the Event logger, and last but not least, understanding how
to effectively use ‘UserControls ’ to create the interface of an application. All of these topics
collectively define the C# programming paradigm and we hope that the reader learns and
understands the core concept of every topic and discussion in these chapters. Exposure to a
programming language can go a long way in a person’s programming career as someone might
have to reverse engineer a mechanism built using programming languages like C#, C++, etc. So
it’s recommended always to have the eagerness to learn a programming language no matter how
intriguing it may seem.
References