Professional Documents
Culture Documents
Chapter Topic
Page 2 of 65
Page 3 of 65
only need to run when they require service. Many server applications allow for
multiple clients to request service. For example, while you are reading this
page others interested in client-server programming could also request and
read the same Web page.
Features of a client/server application:
Client/Server Benefits:
Most of the benefits of using client/server architecture for enterprise
applications
relate to
flexibility
of
deployment
and
relative ease
of
maintenance.
Page 4 of 65
Page 5 of 65
2.
3.
4.
Page 6 of 65
5.
The visibility principle. Your design should keep all needed options
and materials for a given task visible without distracting the user with
extraneous or redundant information. Good designs dont overwhelm
users with too many alternatives or confuse them with unneeded
information.
6.
7.
8.
1.
Page 7 of 65
2.
Set standards and stick to them. The only way you can ensure
consistency within your application is to set user interface design
standards, and then stick to them. You should follow Agile Modeling
(AM)s Apply Modeling Standards practice in all aspects of software
development, including user interface design.
3.
Be prepared to hold the line. When you are developing the user
interface for your system you will discover that your stakeholders often
have some unusual ideas as to how the user interface should be
developed. You should definitely listen to these ideas but you also
need to make your stakeholders aware of your corporate UI standards
and the need to conform to them.
4.
Explain the rules. Your users need to know how to work with the
application you built for them. When an application works consistently,
it means you only have to explain the rules once. This is a lot easier
than explaining in detail exactly how to use each feature in an
application step-by-step.
5.
6.
7.
Word your messages and labels effectively. The text you display
on your screens is a primary source of information for your users. If
your text is worded poorly, then your interface will be perceived poorly
by your users. Using full words and sentences, as opposed to
abbreviations and codes, makes your text easier to understand. Your
messages should be worded positively, imply that the user is in
control, and provide insight into how to use the application properly.
Page 8 of 65
For example, which message do you find more appealing You have
input the wrong information or An account number should be eight
digits in length. Furthermore, your messages should be worded
consistently and displayed in a consistent place on the screen.
Although the messages The persons first name must be input and
An account number should be input are separately worded well,
together they are inconsistent. In light of the first message, a better
wording of the second message would be The account number must
be input to make the two messages consistent.
8.
Understand the UI widgets. You should use the right widget for the
right task, helping to increase the consistency in your application and
probably making it easier to build the application in the first place. The
only way you can learn how to use widgets properly is to read and
understand the user-interface standards and guidelines your
organization has adopted.
9.
Page 9 of 65
12. Align fields effectively. When a screen has more than one editing
field, you want to organize the fields in a way that is both visually
appealing and efficient. I have always found the best way to do so is to
left-justify edit fields: in other words, make the left-hand side of each
edit field line up in a straight line, one over the other. The
corresponding labels should be right-justified and placed immediately
beside the field. This is a clean and efficient way to organize the fields
on a screen.
13. Expect your users to make mistakes. How many times have you
accidentally deleted some text in one of your files or deleted the file
itself? Were you able to recover from these mistakes or were you
forced to redo hours, or even days, of work? The reality is that to err is
human, so you should design your user interface to recover from
mistakes made by your users.
14. Justify data appropriately. For columns of data, common practice
is to right-justify integers, decimal align floating-point numbers, and to
left-justify strings.
15. Your design should be inimitable. In other words, if your users
dont know how to use your software, they should be able to determine
how to use it by making educated guesses. Even when the guesses are
wrong, your system should provide reasonable results from which your
users can readily understand and ideally learn
16. Dont create busy user interfaces. Crowded screens are difficult to
understand and, hence, are difficult to use. Experimental results show
that the overall density of the screen should not exceed 40 percent,
whereas local density within groupings should not exceed 62 percent.
Page 10 of 65
a blank slate that you, as a developer, enhance with controls to create a user
interface and with code to manipulate data. To that end, Visual Studio
provides you with an integrated development environment (IDE) to aid in
writing code, as well as a rich control set written with the .NET Framework. By
complementing the functionality of these controls with your code, you can
easily and quickly develop the solutions you need.
Button : The Button control presents a standard command button, which is
rendered as an HTML input element. Using a Button control on ASP.NET web
pages allows users to indicate that they have completed the form or that they
want to perform a specific command. Web server controls include three kinds
of buttons, each of which appears differently on web pages: Button controls,
LinkButton control controls, and ImageButton control controls.
When a user clicks any of the three types of buttons, a form is submitted to
the server. This causes the web page to be processed and any pending events
to be raised in server-based code.
Label: Label controls usually provide information in the user interface (UI).
Historically, a Label has contained only text, but because the Label that ships
with Windows Presentation Foundation (WPF) is a ContentControl, it can
contain either text or a UIElement.
A Label provides both functional and visual support for access keys. It is
frequently used to enable quick keyboard access to controls such as a
TextBox. To assign a Label to a Control, set the Label.Target property to the
control that should get focus when the user presses the access key.
TextBox: Windows Forms text boxes are used to get input from the user or to
display text. The TextBox control is generally used for editable text, although
it can also be made read-only. Text boxes can display multiple lines, wrap text
to the size of the control, and add basic formatting. The TextBox control
allows a single format for text displayed or entered in the control.
ListBox: Defines commonly used controls for a dialog box or window. The
control is a rectangle containing a list of strings (such as filenames) from
which the user can select.
The LISTBOX statement, which can only be used in a WINDOW statement,
defines the identifier, dimensions, and attributes of a control window.
CheckBox: This CheckBox_control is a two-state check box. To associate an
integer or string property with this control, enter the property name into the
Property column of the Control table. The selected state of the box sets the
property either to the value specified in the Value column of the CheckBox
table or to the initial value of the property specified in the Property table. If
the property has no initial value, the checked state sets it to 1. The
unselected state sets the property to null.
Page 11 of 65
LinkLabel: The Windows Forms LinkLabel control allows you to add Webstyle links to Windows Forms applications. You can use the LinkLabel control
for everything that you can use the Label control for; you also can set part of
the text as a link to an object or Web page.
RadioButton:
You can use two types of ASP.NET controls to add radio
buttons to a page: individual RadioButton controls or a RadioButtonList
control. Both controls allow users to select from a small set of mutually
exclusive, predefined choices. The controls allow you to define any number of
radio buttons with labels and to arrange them horizontally or vertically. For a
comparison of RadioButton and RadioButtonList controls, see RadioButtonList
control.
To add a RadioButton control to a page
1. Drag the RadioButton control from the Toolbox task pane to your page.
2. Set properties for the control in the Tag Properties task pane.
DataGridView: The DataGridView control provides a powerful and flexible
way to display data in a tabular format. You can use the DataGridView control
to show read-only views of a small amount of data, or you can scale it to show
editable views of very large sets of data.
You can extend the DataGridView control in a number of ways to build custom
behaviors into your applications. For example, you can programmatically
specify your own sorting algorithms, and you can create your own types of
cells. You can easily customize the appearance of the DataGridView control by
choosing among several properties. Many types of data stores can be used as
a data source, or the DataGridView control can operate with no data source
bound to it.
Page 12 of 65
Page 13 of 65
compiled and executed on the server by the framework, and then the
framework generates the HTML markup that the browser can render. An
ASP.NET Web Forms page presents information to the user in any browser or
client device.
LinkButton: The LinkButton control renders as a hyperlink in the page.
However, it contains client-side script that causes the form to be posted back
to the server.
To add a LinkButton control to a page
1. Drag the LinkButton control from the Toolbox task pane to your page.
2. Set properties for the control in the Tag Properties task pane.
Page 14 of 65
Page 15 of 65
DataList: The DataList control displays data in a format that you can define
using templates and styles. Its useful for data in any repeating structure,
such as a table. The DataList control can display rows in different layouts,
such as ordering them in columns or rows.
GridView: A recurring task in software development is to display tabular
data. ASP.NET provides a number of tools for showing tabular data in a grid,
including the GridView control. With the GridView control, you can display,
edit, and delete data from many different kinds of data sources, including
databases, XML files, and business objects that expose data.
The GridView control displays data in read-only
also supports an edit mode in which it displays
controls such as TextBoxor CheckBoxcontrols.
GridView control to display a Delete button that
corresponding record from the data source.
ListView: The ListView control displays items using one of four different
views. You can arrange items into columns with or without column headings
as well as display accompanying icons and text. The View property
determines which view the control uses to display the items in the list. You
can also control whether the labels associated with items in the list wrap to
more than one line using the LabelWrap property. In addition, you can
manage how items in the list are sorted and how selected items appear.
Page 16 of 65
5. ListBox
6. CheckBox
7. LinkLabel
8. RadioButto
n
9. DataGridView
10. MenuStrip
11. FileSystemWatch
er
12. DateTimePicker
13. TreeView
14. GroupBox
15. ComboBox
2. GridView
3. ListView
4. SqlDataSource
1. DataList: The DataList control displays data in a format that you can define using
templates and styles.
2. GridView: With the GridView control, you can display, edit, and delete data from
many different kinds of data sources, including databases, XML files, and business
objects that expose data.
3. ListView: The ListView control is useful for displaying data in any repeating
structure, similar to the DataList.
4. SqlDataSource: The SqlDataSource control enables you to use a web control to
access data located in a relational data base.
Page 17 of 65
5. CheckBox
6. CheckBoxList
7. RadioButton
8. RadioButtonList
9. HyperLink
10. ListBox
11. Panel
12. Image
13. ImageButton
14. DropDownList
15. LinkButton
1. WebForms: Web Forms are pages that your users request using their browser.
These pages can be written using a combination of HTML, client-script, server
controls, and server code.
2. LinkButton: The LinkButton control is used to create a hyperlink button.
3. CheckBoxList: The CheckBoxList control is used to create a multi-selection check
box group.
4. RadioButtonList: Control is used to create a group of radio buttons.
5. HyperLink: Control is used to create a hyperlink.
6. Panel: Provides a container for other controls.
7. Image: Displays an image.
8. ImageButton: Displays a clickable image.
9. DropDownList: The DropDownList control is used to create a drop-down list. Each
selectable item in a DropDownList control is defined by a ListItem element.
N.B.:Similar type of controls description given in above section.
3. Input(File)
4. Input(CheckBo
x)
5. Input(Radio)
6. Table
7. Select
8. Image
Page 18 of 65
DATABASE DEVELOPMENT:
Database Name: BIM2015DB
Tables:
1. PUBSINF - Consists records for publishers general
information
2. TITLES - Consists records for books general information
Table Structure: PUBSINF
Column Name
pub_id
pub_name
pr_info
Data Type
char(4)
nvarchar(100)
text
Allow
Null
Descriptions
Publisher ID (Primary Key)
Publisher Name
Publisher details description
Data Type
varchar(6)
varchar(80)
char(12)
pub_id
price
pubdate
char(4)
decimal(18, 6)
datetime
Allow
Null
Descriptions
Book ID (Primary Key)
Title of the book
Book type
Publisher ID (Foreign Key from
PUBSINF)
Sales Price of the book
Publishing Date
Records: PUBSINF
pub_id
pub_name
0736
0877
1389
1622
1756
9901
9952
9999
Algodata Infosystems
Five Lakes Publishing
Ramona Publishers
GGG&G, publisher
Scootney Books
Lucerne publishing
pr_info
New Moon Books is located in Boston, Massachusetts.
Binnet & Hardley is located in Washington, D.C.
Algodata Infosystems is located in Berkeley,
California.
Five Lakes Publishing is located in Chicago, Illinois.
Ramona Publishers is located in Dallas, Texas.
GGG&G is located in Mnchen, Germany.
Scootney Books is located in New York City, New York.
Lucerne publishing is located in Paris, France.
Page 19 of 65
Records: TITLES
title_i
d
BU103
2
BU111
1
BU207
5
BU783
2
MC22
22
MC30
21
MC30
26
PC103
5
PC665
5
PC665
6
PC666
6
PC888
8
PC999
9
PS137
2
PS209
1
PS333
3
TC321
8
TC420
3
TC777
7
ptype
Pub_i
d
price
business
1389
19.99
business
1389
11.95
business
0736
2.99
business
1389
19.99
mod_cook
0877
19.99
mod_cook
0877
2.99
UNDECIDED
0877
NULL
popular_com
p
popular_com
p
popular_com
p
popular_com
p
popular_com
p
popular_com
p
psychology
1389
22.95
1389
25.00
1389
55.00
1389
25.00
1389
20.00
1389
NULL
0877
21.59
psychology
0736
10.95
psychology
0736
19.99
trad_cook
0877
20.95
trad_cook
0877
11.95
trad_cook
0877
14.99
title
Pubdate
1991-06-12
00:00:00
1991-06-09
00:00:00
1991-06-30
00:00:00
1991-06-22
00:00:00
1991-06-09
00:00:00
1991-06-18
12:00:00
2004-12-13
16:11:36
1991-06-30
12:40:00
2005-06-12
12:45:00
2008-06-12
12:45:00
2001-06-12
00:00:00
1994-06-12
00:00:00
2004-12-13
16:11:36
1991-10-21
00:00:00
1991-06-15
00:00:00
1991-06-12
00:00:00
1991-10-21
00:00:00
1991-06-12
00:00:00
1995-06-12
12:40:00
Page 20 of 65
Page 21 of 65
Page 22 of 65
From System.Data.SqlClient;
Page 23 of 65
SqlConnection
SqlCommand
SqlDataAdapter
SqlConnection SCon1 = new SqlConnection("Data Source=ASIT-03\\SQL2K5EXP;
Initial Catalog=BIM2015DB;Integrated Security=True");
From System.Data;
DataSet
DataTable
Page 24 of 65
using
using
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Linq;
System.Text;
System.Windows.Forms;
System.Data.SqlClient;
namespace BIMWINAPP
{
public partial class Form1 : Form
{
SqlConnection SCon1 = new SqlConnection("Data Source=ASIT-03\\SQL2K5EXP;
Initial Catalog=BIM2015DB;Integrated Security=True");
DataTable tblTitle, tblPubs;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnShow_Click(object sender, EventArgs e)
{
string SqlStatment1 = "";
//SqlStatment1 = "select * from titles";
SqlStatment1 = "select title_id, title, ptype, pub_id, ";
SqlStatment1 += "price = isnull(price, 0.00), pubdate from titles;";
SqlStatment1 += "select pub_id, pub_name from pubsinf;";
SqlCommand SCmd1 = new SqlCommand();
SCmd1.CommandText = SqlStatment1;
SCmd1.Connection = SCon1;
DataSet ds1 = new DataSet();
SqlDataAdapter SDap1 = new SqlDataAdapter(SCmd1);
SDap1.Fill(ds1);
tblTitle = ds1.Tables[0];
tblPubs = ds1.Tables[1];
this.dgv1.AutoGenerateColumns = false;
this.dgv1.DataSource = tblTitle;
this.groupBox1.Enabled = true;
Page 25 of 65
Page 26 of 65
private void btnInsert_Click(object sender, EventArgs e)
{
string _insertID = this.txt_title_id.Text.Trim();
DataRow[] dr1 = tblTitle.Select("title_id = '" + _insertID + "'");
if (dr1.Length > 0)
{
MessageBox.Show("titel_id " + _insertID + " already exist",
"Record Insert Not Possible", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return;
}
string _titleDes = this.txt_title.Text.Trim();
string _tptype = this.txt_ptype.Text.Trim();
string _pubid = this.txt_pub_id.Text.Trim().Substring(0, 4);
string _sprice = "0" + this.txt_price.Text.Trim().Replace(",", "");
string _pudate = this.txt_pubdate.Text.Trim();
if (MessageBox.Show("Are you sure to Insert record for ID = "
+ _insertID, "Confirmation", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question) != DialogResult.Yes)
{
return;
}
// title, ptype, pub_id, price = isnull(price, 0.00), pubdate
string SqlStatment1 = "insert into titles (title_id, title, ptype, pub_id, ";
SqlStatment1 += "price, pubdate) values ('" + _insertID + "', '" + _titleDes;
SqlStatment1 += "', '" + _tptype + "', '" + _pubid + "', ";
SqlStatment1 += _sprice + ", '" + _pudate + "')";
SqlCommand SCmd1 = new SqlCommand();
SCmd1.CommandText = SqlStatment1;
SCmd1.Connection = SCon1;
SCon1.Open();
int _result = SCmd1.ExecuteNonQuery();
SCon1.Close();
if (_result < 0)
{
MessageBox.Show("Record not inserted");
return;
}
this.btnShow_Click(null, null);
int RecNo = 0;
for (int i = 0; i < tblTitle.Rows.Count; i++)
{
if (tblTitle.Rows[i]["title_id"].ToString().Trim() == _insertID)
{
RecNo = i;
break;
}
}
this.dgv1.CurrentCell = this.dgv1[1, RecNo];
this.ShowRecord(RecNo);
}
Page 27 of 65
private void btnUpdate_Click(object sender, EventArgs e)
{
int RecNo = this.dgv1.CurrentRow.Index;
string _updateID = this.txt_title_id.Text.Trim();
string _titleDes = this.txt_title.Text.Trim();
string _tptype = this.txt_ptype.Text.Trim();
string _pubid = this.txt_pub_id.Text.Trim().Substring(0, 4);
string _sprice = "0"+ this.txt_price.Text.Trim().Replace(",", "");
string _pudate = this.txt_pubdate.Text.Trim();
Page 28 of 65
}
}
this.groupBox1.Enabled = false;
this.dgv1.DataSource = null;
Page 29 of 65
Variables are used to store values. More technically, a variable binds an object (in the general sense
of the term, i.e. a specific value) to an identifier (the variable's name) so that the object can be
accessed later. Variables can, for example, store a value for later use:
Fields
Fields, sometimes called class-level variables, are variables associated with classes or structures.
An instance variable is a field associated with an instance of the class or structure, while a static
variable, declared with the static keyword, is a field associated with the type itself. Fields can also be
associated with their class by making them constants (const), which requires a declaration
assignment of a constant value and prevents subsequent changes to the field.
Each field has a visibility of public, protected, internal, protected internal, or private (from most visible
to least visible).
Local variables
Like fields, local variables can optionally be constant (const). Constant local variables are stored in
the assembly data region, while non-constant local variables are stored on (or referenced from) the
stack. They thus have both a scope and an extent of the method or statement block that declares
them.
Parameter
Parameters are variables associated with a method.
The built-in C# type aliases and their equivalent .NET Framework types follow:
Page 30 of 65
Integers
Floating-point
Page 31 of 65
Introduction:
Welcome to the C# Station Tutorial This is a set of lessons suited for beginning to intermediate
programmers or anyone who would like to gain familiarity with the C# programming language. These
lessons will help you get a quick head-start with C# programming.
To get started, you will need a compiler and an editor. There are several options for obtaining a
compiler to write C# programs. A free option is to download the .NET Frameworks SDK and use
Notepad. Of course there are many editor and IDE options available, so see the Tools section to select
the option that's right for you. Most of the examples in these tutorials run as console programs.
Microsoft Visual Studio is also available in multiple versions as well as a free download for Visual Studio
Express.
This tutorial is a work in progress. It's quality is a product of volunteer reviews and valuable feedback
received from many readers. Please visit periodically for the latest updates and new lessons.
Once you've completed this tutorial, you may be interested in additional resources to continue learning
C#. There are also additional Articleson this site.
I hope you enjoy the tutorial, and best of luck!
Joe
Follow Joe Mayo on Twitter.
References:
C# Language Reference and Specifications
Standard ECMA-334 C# Language Specification
Lessons:
Lesson 01: Getting Started
Lesson 02: Expressions, Types, and Variables
Lesson 03: Control Statements - Selection
Lesson 04: Control Statements - Loops
Lesson 05: Methods
Lesson 06: Namespaces
Lesson 07: Introduction to Classes
Lesson 08: Class Inheritance
Page 32 of 65
Lesson 09: Polymorphism
Lesson 10: Properties
Lesson 11: Indexers
Lesson 12: Structs
Lesson 13: Interfaces
Lesson 14: Introduction to Delegates and Events
Lesson 15: Introduction to Exception Handling
Lesson 16: Using Attributes
Lesson 17: Enums
Lesson 18: Overloading Operators
Lesson 19: Encapsulation
Lesson 20: Introduction to Generic Collections
Lesson 21: Anonymous Methods
Lesson 22: Topics on C# Type
Lesson 23: Working with Nullable Types
Page 33 of 65
Page 34 of 65
Console.WriteLine("The statement above is not {0}.", noContent);
}
}
In Listing 2-1, the boolean values are written to the console as a part of a sentence. The only legal
values for the bool type are either true orfalse, as shown by the assignment
of true to content and false to noContent. When run, this program produces the following output:
Integral Types
In C#, an integral is a category of types. For anyone confused because the word Integral sounds like a
mathematical term, from the perspective of C# programming, these are actually defined as Integral
types in the C# programming language specification. They are whole numbers, either signed or
unsigned, and the char type. The char type is a Unicode character, as defined by the Unicode Standard.
For more information, visit The Unicode Home Page. table 2-1 shows the integral types, their size, and
range.
Range
sbyte
-128 to 127
byte
0 to 255
short
16
-32768 to 32767
ushort
16
0 to 65535
int
32
-2147483648 to 2147483647
uint
32
0 to 4294967295
long
64
-9223372036854775808 to 9223372036854775807
ulong
64
0 to 18446744073709551615
char
16
0 to 65535
Integral types are well suited for those operations involving whole number calculations. The char type is
the exception, representing a single Unicode character. As you can see from the table above, you have
a wide range of options to choose from, depending on your requirements.
Page 35 of 65
Table 2-2. The Floating Point and Decimal Types with Size, precision, and Range
Type
precision
Range
float
32
7 digits
double
64
15-16 digits
decimal
128
Floating point types are used when you need to perform operations requiring fractional representations.
However, for financial calculations, the decimal type is the best choice because you can avoid rounding
errors.
Meaning
\'
Single Quote
\"
Double Quote
\\
Backslash
\0
\a
Bell
\b
Backspace
\f
form Feed
\n
Newline
\r
Carriage Return
\t
Horizontal Tab
\v
Vertical Tab
Another useful feature of C# strings is the verbatim literal, which is a string with a @ symbol prefix, as
in @"Some string". Verbatim literals make escape sequences translate as normal characters to enhance
readability. To appreciate the value of verbatim literals, consider a path statement such
as "c:\\topdir\\subdir\\subdir\\myapp.exe". As you can see, the backslashes are escaped, causing the
Page 36 of 65
string to be less readable. You can improve the string with a verbatim literal, like
this: @"c:\topdir\subdir\subdir\myapp.exe".
That is fine, but now you have the problem where quoting text is not as easy. In that case, you would
specify double double quotes. For example, the string "copy \"c:\\source file name with spaces.txt\"
c:\\newfilename.txt" would be written as the verbatim literal @"copy ""c:\source file name with
spaces.txt"" c:\newfilename.txt".
C# Operators
Results are computed by building expressions. These expressions are built by combining variables and
operators together into statements. The following table describes the allowable operators, their
precedence, and associativity.
Operator(s)
Associativity
Primary
left
Unary
right
Multiplicative
* / %
left
Additive
+ -
left
Shift
<< >>
left
Relational
left
Equality
== !=
right
Logical AND
&
left
Logical XOR
left
Logical OR
left
Conditional AND
&&
left
Conditional OR
||
left
Null Coalescing
??
left
Ternary
?:
right
Assignment
right
Left associativity means that operations are evaluated from left to right. Right associativity mean all
operations occur from right to left, such as assignment operators where everything to the right is
evaluated before the result is placed into the variable on the left.
Page 37 of 65
Most operators are either unary or binary. Unary operators form expressions on a single variable, but
binary operators form expressions with two variables. Listing 2-2 demonstrates how unary operators
are used.
Page 38 of 65
In Listing 2-2, the unary variable is initialized to zero. When the pre-increment (++x) operator is
used, unary is incremented to 1 and the value 1 is assigned to the preIncrement variable. The predecrement (--x) operator
turns unary back
to
a
0
and
then
assigns
the
value
to
thepreDecrement variable.
When the post-decrement (x--) operator is used, the value of unary, 0, is placed into
the postDecrement variable and then unary is decremented to -1. Next the post-increment (x+
+) operator moves the current value of unary, -1, to the postIncrement variable and then
increments unary to 0.
The variable bitNot is initialized to 0 and the bitwise not (~) operator is applied. The bitwise
not (~) operator flips the bits in the variable. In this case, the binary representation of 0, "00000000",
was transformed into -1, "11111111".
While the (~) operator works by flipping bits, the logical negation operator (!) is a logical operator that
works on bool values, changing true tofalse or false to true. In the case of the logNot variable in Listing
2-2, the value is initialized to false, and the next line applies the logical negation operator, (!), which
returns true and reassigns the new value, true, to logNot. Essentially, it is toggling the value of
the bool variable,logNot.
The setting of positive is a little tricky. At the time that it is set, the postIncrement variable is equal to
-1. Applying the minus (-) operator to a negative number results in a positive number, meaning
that positive will equal 1, instead of -1. The minus operator (-), which is not the same as the predecrement operator (--), doesn't change the value of postInc - it just applies a sign negation. The plus
operator (+) doesn't affect the value of a number, assigning negative with the same value
as postIncrement, -1.
Notice the expression (sbyte)(~bitNot). Any operation performed on types sbyte, byte, short,
or ushort return int values. To assign the result into the bitNot variable we had to use a cast, (Type),
operator, where Type is the type you wish to convert to (in this case - sbyte). The cast operator is
shown as the Unary operator, (T)x, in table 2-4. Cast operators must be performed explicity when you
go from a larger type to a smaller type because of the potential for lost data. Generally speaking,
assigning a smaller type to a larger type is no problem, since the larger type has room to hold the
entire value. Also be aware of the dangers of casting between signed and unsigned types. You want to
be sure to preserve the integrity of your data. Many basic programming texts contain good descriptions
of bit representations of variables and the dangers of explicit casting.
Here's the output from the Listing 2-2:
pre-Increment: 1
pre-Decrement 0
Post-Decrement: 0
Post-Increment: -1
Final Value of Unary: 0
Positive: 1
Negative: -1
Bitwise Not: -1
Logical Not: true
In addition to unary operators, C# has binary operators that form expressions of two variables. Listing
2-3 shows how to use the binary operators.
Page 39 of 65
x+y: 12
x-y: 2
x*y: 35
x/y: 1
x/y: 1.4
x%y: 2
result+=x: 9
Listing 2-3 shows several examples of binary operators. As you might expect, the results of addition
(+), subtraction (-), multiplication (*), and division (/) produce the expected mathematical results.
The floatresult variable is a floating point type. We explicitly cast the integer variables x and y to
calculate a floating point value.
There is also an example of the remainder(%) operator. It performs a division operation on two values
and returns the remainder.
The last statement shows another form of the assignment with operation (+=) operator. Any time you
use the assignment with operation operator, it is the same as applying the binary operator to both the
Page 40 of 65
left hand and right hand sides of the operator and putting the results into the left hand side. The
example could have been written as result = result + x; and returned the same value.
Page 41 of 65
Next is a jagged array, myBools. It is essentially an array of arrays. We needed to use the new operator
to instantiate the size of the primary array and then use the new operator again for each sub-array.
The third example is a two dimensional array, myDoubles. Arrays can be multi-dimensional, with each
dimension separated by a comma. It must also be instantiated with the new operator.
One of the differences between jagged arrays, myBools[][], and multi-dimension arrays, myDoubles[,],
is that a multi-dimension array will allocate memory for every element of each dimension, whereas a
jagged array will only allocate memory for the size of each array in each dimension that you define.
Most of the time, you'll be using multi-dimension arrays, if you need multiple dimensions, and will only
use jagged arrays in very special circumstances when you are able to save significant memory by
explicitly specifying the sizes of the arrays in each dimension.
Finally, we have the single-dimensional array of string types, myStrings.
In each case, you can see that array elements are accessed by identifying the integer index for the item
you wish to refer to. Arrays sizes can be any int type value. Their indexes begin at 0.
Summary
A variable is an identifier with a type that holds a value of that type. Simple types include the integrals,
floating points, decimal, and bool. C# has several mathematical and logical operators that participate in
forming expressions. C# also offers the single dimension, multi-dimension and jagged array types.
In this lesson you learned how to write simple statements and code a program that works linearly from
start to finish. However, this is not as useful as it can be because you need to be able to make decisions
and execute different blocks of code depending on different conditions. I invite you to return for Lesson
3: Control Statements - Selection, where you can learn how to branch your logic for more powerful
decision making.
Page 42 of 65
Page 43 of 65
}
Console.WriteLine();
}
}
Listing 4-1 shows a simple while loop. It begins with the keyword while, followed by a boolean
expression. All control statements use boolean expressions as their condition for entering/continuing
the loop. This means that the expression must evaluate to either a true or false value. In this case we
are checking the myInt variable to see if it is less than (<) 10. Since myInt was initialized to 0, the
boolean expression will return true the first time it is evaluated. When the boolean expression evaluates
to true, the block immediately following the boolean expression will be executed.
Within the while block we print the number and a space to the console. Then we increment (+
+) myInt to the next integer. Once the statements in the while block have executed, the boolean
expression is evaluated again. This sequence will continue until the boolean expression evaluates
to false. Once the boolean expression is evaluated as false, program control will jump to the first
statement following thewhile block. In this case, we will write the numbers 0 through 9 to the console,
exit the while block, and print a new line to the console.
The do Loop
A do loop is similar to the while loop, except that it checks its condition at the end of the loop. This
means that the do loop is guaranteed to execute at least one time. On the other hand, a while loop
evaluates its boolean expression at the beginning and there is generally no guarantee that the
statements inside the loop will be executed, unless you program the code to explicitly do so. One
reason you may want to use a do loop instead of a while loop is to present a message or menu such as
the one in Listing 4-2 and then retrieve input from a user.
Page 44 of 65
case "A":
case "a":
Console.WriteLine("You wish to add an address.");
break;
case "D":
case "d":
Console.WriteLine("You wish to delete an address.");
break;
case "M":
case "m":
Console.WriteLine("You wish to modify an address.");
break;
case "V":
case "v":
Console.WriteLine("You wish to view the address list.");
break;
case "Q":
case "q":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("{0} is not a valid choice", myChoice);
break;
}
// Pause to allow the user to see the results
Console.Write("press Enter key to continue...");
Console.ReadLine();
Console.WriteLine();
} while (myChoice != "Q" && myChoice != "q"); // Keep going until the user
wants to quit
}
}
Listing 4-2 shows a do loop in action. The syntax of the do loop is do { <statements> } while
(<boolean expression>);. The statements can be any valid C# programming statements you like. The
boolean expression is the same as all others we've encountered so far. It returns either true or false.
In the Main method, we declare the variable myChoice of type string. Then we print a series of
statements to the console. This is a menu of choices for the user. We must get input from the user,
which is in the form of a Console.ReadLine method which returns the user's value into
the myChoice variable. We must take the user's input and process it. A very efficient way to do this is
with a switch statement. Notice that we've placed matching upper and lower case letters together to
obtain the same functionality. This is the only legal way to have automatic fall through between cases.
If you were to place any statements between two cases, you would not be able to fall through. Another
point is that we used the default: case, which is a very good habit for the reasons stated in Lesson 3:
Control Statements - Selection.
Page 45 of 65
The initializer list is a comma separated list of expressions. These expressions are evaluated only once
during the lifetime of the for loop. This is a one-time operation, before loop execution. This section is
commonly used to initialize an integer to be used as a counter.
Once the initializer list has been evaluated, the for loop gives control to its second section, the boolean
expression. There is only one boolean expression, but it can be as complicated as you like as long as
the result evaluates to true or false. The boolean expression is commonly used to verify the status of a
counter variable.
When the boolean expression evaluates to true, the statements within the curly braces of the for loop
are executed. After executing for loop statements, control moves to the top of loop and executes the
iterator list, which is normally used to increment or decrement a counter. The iterator list can contain a
comma separated list of statements, but is generally only one statement. Listing 4-3 shows how to
implement a forloop. The purpose of the program is to print only odd numbers less than 10.
Page 46 of 65
Similar to the while loop, a for loop will continue as long as the boolean expression is true. When the
boolean expression becomes false, control is transferred to the first statement following the for block.
For this tutorial, I chose to implement break and continue statements in Listing 4-3 only. However, they
may be used in any of the loop statements.
declare
and initialize
Page 47 of 65
In the foreach loop, we've used a string variable, person, as the item name, to hold each element of
the names array. As long as there are names in the array that have not been returned,
the Console.WriteLine method will print each value of the person variable to the screen.
Summary
Loops allow you to execute a block of statements repeatedly. C# offers several statements to construct
loops with, including the while, do, for, and foreach loops. while loops execute a block of statements as
long as an expression is true, do loops execute a block of statements at least once and then keep going
as long as a condition is true, for loops execute a block of statements a specified amount of times,
and foreach loops execute a block of statements for each item in a collection. Normally a block of
statements will execute from beginning to end. However, the normal flow of a loop can be changed with
the break and continue statements.
So far, the only method you've seen in this tutorial is the Main method, which is the entry point of a C#
application. However, you are probably wanting to write larger programs to test your new knowledge.
This requires breaking up the code into methods to keep it organized and logical. For this, I invite you
to return for Lesson 5: Introduction to Methods, where you can learn new techniques of organizing your
code.
Page 48 of 65
Arrays Tutorial
This tutorial describes arrays and shows how they work in C#.
Further Reading
Arrays
12. Arrays
foreach, in
Tutorial
This tutorial is divided into the following sections:
Arrays in General
Declaring Arrays
Initializing Arrays
Arrays in General
C# arrays are zero indexed; that is, the array indexes start at zero. Arrays in C# work similarly to how
arrays work in most other popular languages There are, however, a few differences that you should be
aware of.
When declaring an array, the square brackets ([]) must come after the type, not the identifier. Placing
the brackets after the identifier is not legal syntax in C#.
Page 49 of 65
Another detail is that the size of the array is not part of its type as it is in the C language. This allows
you to declare an array and assign any array of int objects to it, regardless of the array's length.
int[] numbers; // declare numbers as an int array of any size
numbers = new int[10]; // numbers is a 10-element array
numbers = new int[20]; // now it's a 20-element array
Declaring Arrays
C# supports single-dimensional arrays, multidimensional arrays (rectangular arrays), and array-ofarrays (jagged arrays). The following examples show how to declare different kinds of arrays:
Single-dimensional arrays:
int[] numbers;
Multidimensional arrays:
string[,] names;
Array-of-arrays (jagged):
byte[][] scores;
Declaring them (as shown above) does not actually create the arrays. In C#, arrays are objects
(discussed later in this tutorial) and must be instantiated. The following examples show how to create
arrays:
Single-dimensional arrays:
int[] numbers = new int[5];
Multidimensional arrays:
string[,] names = new string[5,4];
Array-of-arrays (jagged):
byte[][] scores = new byte[5][];
for (int x = 0; x < scores.Length; x++)
{
scores[x] = new byte[4];
}
You can also have larger arrays. For example, you can have a three-dimensional rectangular array:
int[,,] buttons = new int[4,5,3];
You can even mix rectangular and jagged arrays. For example, the following code declares a singledimensional array of three-dimensional arrays of two-dimensional arrays of type int:
int[][,,][,] numbers;
Page 50 of 65
Example
The following is a complete C# program that declares and instantiates arrays as discussed above.
// arrays.cs
using System;
class DeclareArraysSample
{
public static void Main()
{
// Single-dimensional array
int[] numbers = new int[5];
// Multidimensional array
string[,] names = new string[5,4];
// Array-of-arrays (jagged array)
byte[][] scores = new byte[5][];
// Create the jagged array
for (int i = 0; i < scores.Length; i++)
{
scores[i] = new byte[i+3];
}
// Print length of each row
for (int i = 0; i < scores.Length; i++)
{
Console.WriteLine("Length of row {0} is {1}", i, scores[i].Length);
}
}
}
Output
Length
Length
Length
Length
Length
of
of
of
of
of
row
row
row
row
row
0
1
2
3
4
is
is
is
is
is
3
4
5
6
7
Initializing Arrays
C# provides simple and straightforward ways to initialize arrays at declaration time by enclosing the
initial values in curly braces ({}). The following examples show different ways to initialize different kinds
of arrays.
Page 51 of 65
Note If you do not initialize an array at the time of declaration, the array members are automatically
initialized to the default initial value for the array type. Also, if you declare the array as a field of a type,
it will be set to the default value null when you instantiate the type.
Single-Dimensional Array
int[] numbers = new int[5] {1, 2, 3, 4, 5};
string[] names = new string[3] {"Matt", "Joanne", "Robert"};
You can omit the size of the array, like this:
int[] numbers = new int[] {1, 2, 3, 4, 5};
string[] names = new string[] {"Matt", "Joanne", "Robert"};
You can also omit the new operator if an initializer is provided, like this:
int[] numbers = {1, 2, 3, 4, 5};
string[] names = {"Matt", "Joanne", "Robert"};
Multidimensional Array
int[,] numbers = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = new string[2, 2] { {"Mike","Amy"}, {"Mary","Albert"} };
You can omit the size of the array, like this:
int[,] numbers = new int[,] { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = new string[,] { {"Mike","Amy"}, {"Mary","Albert"} };
You can also omit the new operator if an initializer is provided, like this:
int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = { {"Mike", "Amy"}, {"Mary", "Albert"} };
Page 52 of 65
Accessing array members is straightforward and similar to how you access array members in C/C++.
For example, the following code creates an array called numbers and then assigns a 5 to the fifth
element of the array:
int[] numbers = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
numbers[4] = 5;
The following code declares a multidimensional array and assigns 5 to the member located at [1, 1]:
int[,] numbers = { {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10} };
numbers[1, 1] = 5;
The following is a declaration of a single-dimension jagged array that contains two elements. The first
element is an array of two integers, and the second is an array of three integers:
int[][] numbers = new int[][] { new int[] {1, 2}, new int[] {3, 4, 5}
};
The following statements assign 58 to the first element of the first array and 667 to the second element
of the second array:
numbers[0][0] = 58;
numbers[1][1] = 667;
Page 53 of 65
With multidimensional arrays, you can use the same method to iterate through the elements, for
example:
int[,] numbers = new int[3, 2] {{9, 99}, {3, 33}, {5, 55}};
foreach(int i in numbers)
{
Console.Write("{0} ", i);
}
The output of this example is:
9 99 3 33 5 55
However, with multidimensional arrays, using a nested for loop gives you more control over the array
elements.
Page 54 of 65
Page 55 of 65
you
could
define
them
as List<string> or List<Customer> and
they
only string or Customer objects. In the example above, myInts holds only type int.
would
hold
Using the Add method, you can add as many int objects to the collection as you want. This is different
from arrays, which have a fixed size. The List<T> class has many more methods you can use, such
as Contains, Remove, and more.
There are two parts of the for loop that you need to know about. First, the condition uses
the Count property of myInts. This is another difference between collections and arrays in that an array
uses a Length property for the same thing. Next, the way to read from a specific position in
the List<T> collection, myInts[i], is the exact same syntax you use with arrays.
The next time you start to use a single-dimension array, consider using a List<T> instead. That said, be
sure to let your solution fit the problem and use the best tool for the job. i.e. it's common to work
with byte[] in many places in the .NET Framework.
Page 56 of 65
customers.Add(cust2.ID, cust2);
customers.Add(cust3.ID, cust3);
foreach (KeyValuePair<int, Customer> custKeyVal in customers)
{
Console.WriteLine(
"Customer ID: {0}, Name: {1}",
custKeyVal.Key,
custKeyVal.Value.Name);
}
The customers variable is declared as a Dictionary<int, Customer>. Considering that the formal
declaration of Dictionary is Dictionary<TKey, TValue>, the meaning of customers is that it is
a Dictionary where the key is type int and the value is type Customer. Therefore, any time you add an
entry to the Dictionary, you must provide the key because it is also the key that you will use to extract
a specified Customer from the Dictionary.
I created three Customer objects, giving each an ID and a Name. I'll use the ID as the key and the
entire Customer object as the value. You can see this in the calls to Add, where custX.ID is added as
the key (first parameter) and the custX instance is added as the value (second parameter).
Extracting information from a Dictionary is a little bit different. Iterating through the customers Dictionary with
a foreach loop, the type returned is KeyValuePair<TKey, TValue>, where TKey is type int and TValue is
type Customer because those are the types that the customersDictionary is defined with.
Since custKeyVal is type KeyValuePair<int, Customer> it has Key and Value properties for you to read from. In our
example, custKeyVal.Keywill
hold
the ID for
the Customer instance
and custKeyVal.Value will
hold
the
whole Customer instance. The parameters in theConsole.WriteLine statement demonstrate this by printing out
the ID, obtained through the Key property, and the Name, obtained through the Name property of
the Customer instance that is returned by the Value property.
The Dictionary type is handy for those situations where you need to keep track of objects via some unique identifier.
For your convenience, here's Listing 20-1, shows how both the List and Dictionary collections work.
Page 57 of 65
class Program
{
static void Main(string[] args)
{
List<int> myInts = new List<int>();
myInts.Add(1);
myInts.Add(2);
myInts.Add(3);
for (int i = 0; i < myInts.Count; i++)
{
Console.WriteLine("MyInts: {0}", myInts[i]);
}
Dictionary<int, Customer> customers = new Dictionary<int, Customer>();
Customer cust1 = new Customer(1, "Cust 1");
Customer cust2 = new Customer(2, "Cust 2");
Customer cust3 = new Customer(3, "Cust 3");
customers.Add(cust1.ID, cust1);
customers.Add(cust2.ID, cust2);
customers.Add(cust3.ID, cust3);
foreach (KeyValuePair<int, Customer> custKeyVal in customers)
{
Console.WriteLine(
"Customer ID: {0}, Name: {1}",
custKeyVal.Key,
custKeyVal.Value.Name);
}
Console.ReadKey();
}
}
Whenever coding with the generic collections, add a using System.Collections.Generic declaration to
your file, just as in Listing 20-1.
Summary
Generic collections give you the best of all worlds with the strong typing of arrays and flexibility of nongeneric collections. There are many more generic collections to choose from also, such
as Stack, Queue, and SortedDictionary. Look in the System.Collections.Generic namespace for other
generic collections.
Page 58 of 65
Note
This topic discusses named methods. For information about anonymous functions, see Anonymous
Functions (C# Programming Guide).
Method Signatures
Methods are declared in a class or struct by specifying the access level such as public or private,
optional modifiers such as abstract or sealed, the return value, the name of the method, and any
method parameters. These parts together are the signature of the method.
Note
A return type of a method is not part of the signature of the method for the purposes of method
overloading. However, it is part of the signature of the method when determining the compatibility
between a delegate and the method that it points to.
Method parameters are enclosed in parentheses and are separated by commas. Empty parentheses
indicate that the method requires no parameters. This class contains three methods:
C#
abstract class Motorcycle
{
// Anyone can call this.
public void StartEngine() {/* Method statements here */ }
// Only derived classes can call this.
protected void AddGas(int gallons) { /* Method statements here */ }
// Derived classes can override the base class implementation.
public virtual int Drive(int miles, int speed) { /* Method statements here */
return 1; }
// Derived classes must implement this.
public abstract double GetTopSpeed();
}
Method Access
Page 59 of 65
Calling a method on an object is like accessing a field. After the object name, add a period, the name of
the method, and parentheses. Arguments are listed within the parentheses, and are separated by
commas. The methods of theMotorcycle class can therefore be called as in the following example:
C#
class TestMotorcycle : Motorcycle
{
public override double GetTopSpeed()
{
return 108.4;
}
static void Main()
{
TestMotorcycle moto = new TestMotorcycle();
moto.StartEngine();
moto.AddGas(15);
moto.Drive(5, 20);
double speed = moto.GetTopSpeed();
Console.WriteLine("My top speed is {0}", speed);
}
}
Page 60 of 65
{
// Store input argument in a local variable.
int input = i;
return input * input;
}
When an object of a reference type is passed to a method, a reference to the object is passed. That is,
the method receives not the object itself but an argument that indicates the location of the object. If you
change a member of the object by using this reference, the change is reflected in the argument in the
calling method, even if you pass the object by value.
You create a reference type by using the class keyword, as the following example shows.
C#
public class SampleRefType
{
public int value;
}
Now, if you pass an object that is based on this type to a method, a reference to the object is passed.
The following example passes an object of type SampleRefType to method ModifyObject.
C#
Page 61 of 65
For more information about how to pass reference types by reference and by value, see Passing
Reference-Type Parameters (C# Programming Guide) and Reference Types (C# Reference).
Return Values
Methods can return a value to the caller. If the return type, the type listed before the method name, is
not void, the method can return the value by using the return keyword. A statement with
the return keyword followed by a value that matches the return type will return that value to the
method caller. The return keyword also stops the execution of the method. If the return type is void,
a return statement without a value is still useful to stop the execution of the method. Without
the return keyword, the method will stop executing when it reaches the end of the code block. Methods
with a non-void return type are required to use the return keyword to return a value. For example,
these two methods use the return keyword to return integers:
C#
class SimpleMath
{
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
public int SquareANumber(int number)
{
return number * number;
}
}
To use a value returned from a method, the calling method can use the method call itself anywhere a
value of the same type would be sufficient. You can also assign the return value to a variable. For
example, the following two code examples accomplish the same goal:
int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);
Using a local variable, in this case, result, to store a value is optional. It may help the readability of the
code, or it may be necessary if you need to store the original value of the argument for the entire scope
of the method.
For more information, see return (C# Reference).
Page 62 of 65
Async Methods
By using the async feature, you can invoke asynchronous methods without using explicit callbacks or
manually splitting your code across multiple methods or lambda expressions. The async feature was
introduced Visual Studio 2012.
If you mark a method with the async modifier, you can use the await operator in the method. When
control reaches an await expression in the async method, control returns to the caller, and progress in
the method is suspended until the awaited task completes. When the task is complete, execution can
resume in the method.
Note
An async method returns to the caller when either it encounters the first awaited object thats not yet
complete or it gets to the end of the async method, whichever occurs first.
An async method can have a return type of Task<TResult>, Task, or void. The void return type is used
primarily to define event handlers, where a void return type is required. An async method that returns
void can't be awaited, and the caller of a void-returning method can't catch exceptions that the method
throws.
In the following example, DelayAsync is an async method that has a return type
of Task<TResult>. DelayAsync has areturn statement that returns an integer. Therefore the method
declaration of DelayAsync must have a return type of Task<int>. Because the return type
is Task<int>, the evaluation of the await expression in DoSomethingAsyncproduces an integer as the
following statement demonstrates: int result = await delayTask.
The startButton_Click method is an example of an async method that has a return type of void.
BecauseDoSomethingAsync is an async method, the task for the call to DoSomethingAsync must be
awaited, as the following statement shows: await DoSomethingAsync();. The startButton_Click method
must be defined with the asyncmodifier because the method has an await expression.
C#
// using System.Diagnostics;
// using System.Threading.Tasks;
// This Click event is marked with the async modifier.
private async void startButton_Click(object sender, RoutedEventArgs e)
Page 63 of 65
{
await DoSomethingAsync();
}
private async Task DoSomethingAsync()
{
Task<int> delayTask = DelayAsync();
int result = await delayTask;
// The previous two statements may be combined into
// the following statement.
//int result = await DelayAsync();
Debug.WriteLine("Result: " + result);
}
private async Task<int> DelayAsync()
{
await Task.Delay(100);
return 5;
}
// Output:
// Result: 5
An async method can't declare any ref or out parameters, but it can call methods that have such
parameters.
For more information about async methods, see Asynchronous Programming with Async and Await (C#
and Visual Basic), Control Flow in Async Programs (C# and Visual Basic), and Async Return Types (C#
and Visual Basic).
Page 64 of 65
If the method returns void or is an async method, then the body of the method must be a statement
expression (same as with lambdas). For properties and indexers, they must be read only, and you do not
use the get accessor keyword.
Iterators
An iterator performs a custom iteration over a collection, such as a list or an array. An iterator uses
the yield returnstatement to return each element one at a time. When a yield return statement is
reached, the current location in code is remembered. Execution is restarted from that location when the
iterator is called the next time.
You call an iterator from client code by using a foreach statement.
10. API
11. Database
12. Programming
Page 65 of 65