Professional Documents
Culture Documents
Chapter 3 - C-Sharp Language Funcamentals
Chapter 3 - C-Sharp Language Funcamentals
Chapter 3 - C-Sharp Language Funcamentals
12/19/21 1
The Anatomy of a Simple C# Program
// By convention, C# files end with a *.cs file extension.
using System;
class HelloClass
{
public static int Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.ReadLine();
return 0;
}
}
12/19/21 GRNICA 2
Command line arguements
using System;
class HelloClass1
{
public static void Main(string[] args)
{
Console.WriteLine("Hello.... ");
Console.WriteLine(" "+args[0]);
Console.WriteLine(" "+args[1]);
}
}
12/19/21 3
Using String objects in output
using System;
class HelloClass2
{
public static void Main(string[] args)
{
String name = "c sharp";
Console.WriteLine(name);
}
}
12/19/21 4
GRNICA
A program with two classes
class TestClass
{
public void fun()
{
System.Console.WriteLine("hooooooooooooooo");
}
}
class HelloClass3
{
public static void Main(string[] args)
{
TestClass test = new TestClass();
test.fun();
}
} 12/19/21 GRNICA 5
One more example….
using System;
using System.Windows.Forms;
class HelloMessage
{
public void Speak()
{
MessageBox.Show("Hello...");
}
}
using System;
class TestApps
{
public static void Main()
{
Console.WriteLine("Testing! 1, 2, 3");
HelloMessage h = new HelloMessage();
h.Speak();
12/19/21
} GRNICA 6
}
Interactive console input
using System;
class HelloClass6
{
public static void Main(string[] args)
{
Console.Write("Enter your name:");
String name = Console.ReadLine();
Console.WriteLine("Hello" + name);
}
}
12/19/21 GRNICA 7
Using Mathematics functions
using System;
class HelloClass7
{
public static void Main(string[] args)
{
double x = 5.0,y;
y=Math.Sqrt(x);
Console.WriteLine(" Y = " + y);
}
}
12/19/21 GRNICA 8
Variations on the Main() Method
// No return type, array of strings as argument.
public static void Main(string[] args)
{
}
// Notice you have no need to check the size of the array when using 'foreach'.
public static int Main(string[] args)
{
...
foreach(string s in args)
Console.WriteLine("Arg: {0} ", s);
...
} 12/19/21 GRNICA 10
// Now using System.Environment.
string[] theArgs = Environment.GetCommandLineArgs();
Console.WriteLine("Path is: {0}", theArgs[0]);
12/19/21 GRNICA 11
11
Creating Objects: Constructor Basics
• A class is a definition of a user-defined type (UDT) that is often
regarded as a blueprint for variables of this type.
• An object is simply a term describing a given instance of a
particular
class.
• In C#, the "new" keyword is the way to create an object instance.
//This is no good….
using System;
class HelloClass
{
public static int Main(string[] args)
{
Helloclass c1;
c1.SayHi();
return 0;
}
}12/19/21 GRNICA 12
using System;
class HelloClass
{
public static int Main(string[] args)
{
HelloClass c1 = new HelloClass();
HelloClass c2 = new HelloClass();
return 0;
}
}
12/19/21 GRNICA 13
• The previous HelloClass objects have been constructed using the
default constructor, which by definition never takes arguments.
• Every C# class is automatically provided with a free default
constructor, which you may redefine if need be.
• The default constructor ensures that all member data is set to an
appropriate default value.
12/19/21 GRNICA 14
using System;
class HelloClass8
{
public HelloClass8()
{
Console.WriteLine("Default constructor called.");
}
12/19/21 GRNICA 16
The Composition of a C# Application
• HelloClass8 type has been constructed to perform two duties.
• First, the class defines the entry point of the application.
• Second, HelloClass maintains two custom data members and a few
overloaded constructors.
12/19/21 GRNICA 17
class HelloClass
{
public string userMessage;
public HelloClass()
{ Console.WriteLine("Default ctor called!"); }
public HelloClass(string msg)
{
Console.WriteLine("Custom ctor called!");
userMessage = msg;
}
public void PrintMessage()
{
Console.WriteLine("Message is: {0}", userMessage);
}
}
class HelloApp
{
public static int Main(string[] args)
{
HelloClass c1 = new HelloClass("Hey there...");
c1.PrintMessage();
...
}
}
12/19/21 GRNICA 18
Default Assignments and Variable Scope
• All intrinsic .NET data types have a default value. When custom
types are created, all member variables are automatically assigned to
their appropriate default value.
class DefaultValueTester
{
public sbyte theSignedByte;
public byte theByte;
public short theShort;
public ushort theUShort;
public int theInt;
public uint theUInt;
public long theLong;
public ulong theULong;
public char theChar;
public float theFloat;
public double theDouble;
public bool theBool;
public decimal theDecimal;
public string theStr;
public static int Main(string[] args)
{
DefaultValueTester v = new DefaultValueTester();
return 0;
}
12/19/21 GRNICA 19
}
• When you define variables within a method scope, you must assign
an initial value before you use them, as they do not receive a default
assignment.
// Compiler error! Must assign localInt to an initial value before use.
public static void Main()
{
int localInt;
Console.WriteLine(localInt);
}
12/19/21 GRNICA 20
The C# Member Variable Initialization Syntax
• A class may define various custom constructors, and its annoying
write the same initialization code in each and every constructor
implementation.
• This is particularly necessary if you do not wish to accept the
default values assigned to your state data.
// This is OK, but redundant...
class Test
{
private int myInt;
Test() { myInt = 9; }
Test(string someStringParam)
{ myInt = 9; }
Test(bool someBoolParam)
{ myInt = 9; }
...
}
12/19/21 GRNICA 21
• An alternative would be to define a private helper function for your
class type that is called by each constructor.
// This is OK, but redundant...
class Test
{
private int myInt;
Test() { InitData(); }
Test(string someStringParam)
{ InitData(); }
Test(bool someBoolParam)
{ InitData(); }
private void InitData()
{ myInt = 9; }
...
}
12/19/21 GRNICA 23
Basic Input and Output with the Console Class
• The methods of System.Console are Read(), ReadLine() Write() and
WriteLine(), all of which are defined as static.
• WriteLine() pumps a text string (including a carriage return)
to the output stream.
• The Write() method pumps text to the output stream without a
carriage return.
• ReadLine() allows you to receive information from the input stream
up until the carriage return.
• Read() is used to capture a single character from the input stream.
12/19/21 GRNICA 24
//Make use of the Console class to perform basic IO.
using System;
class BasicIO
{
public static void Main(string[] args)
{
Console.Write("Enter your name:");
String s = Console.ReadLine();
Console.WriteLine("Hello, {0}",s);
Console.Write("Enter your age:");
s = Console.ReadLine();
Console.WriteLine("your are {0} years old", s);
}
}
12/19/21 GRNICA 25
Formatting Textual Output
//Make use of the Console class to perform basic IO.
using System;
class BasicIO
{
public static void Main(string[] args)
{
...
int theInt = 90;
float theFloat = 9.99;
BasicIO myIO = new BasicIO();
//Format a string....
Console.WriteLine("Int is : {0} \n Float is: {1} \n You Are: {2}",
theInt, theFloat, myIO.ToString());
}
}
Console.WriteLine("{0}Number{0}Number{0}", 9);
12/19/21 GRNICA 27
String Formatting Flags
.NET String Format Characters
12/19/21 GRNICA 29
• The use of the C# formatting characters is not limited to the
System.Console.WriteLine() method.
• For example, these same flags can be used within the context of
the static String.Format() method.
• This can be helpful when you need to build a string containing
numerical values in memory and display it at a later time:
12/19/21 GRNICA 30
Understanding Value Types and Reference Types
• A .NET data type may be value-based or reference-based.
• Value-based types include all numerical data types (int, float..) as
well as enumerations and structures, are allocated on the stack.
• Value types can be quickly removed from memory once they fall out
of the defining scope:
//Integers are value types!
public void SomeMethod()
{
int i = 0;
Console.WriteLine(i);
}// 'i' is popped off the stack here!
12/19/21 GRNICA 31
// Assigning two intrinsic value types results in two independent variables on the
stack.
12/19/21 GRNICA 32
using System;
// Structures are value types!
struct FOO
{
public int x, y;
}
class ValRefClass
{
public static int Main(string[] args)
{
FOO f1 = new FOO();
f1.x = 100;
f1.y = 100;
Console.WriteLine("-> Assigning f2 to f1\n");
FOO f2 = f1;
//Here is F1.
Console.WriteLine("F1.x = {0}", f1.x);
Console.WriteLine("F1.y = {0}", f1.y);
//Here is F2.
Console.WriteLine("F2.x = {0}", f2.x);
Console.WriteLine("F2.y = {0}", f2.y);
//Change f2.x. This will not change f1.x
Console.WriteLine("->Changing f2.x to 900");
f2.x=900;
//Print again.
Console.WriteLine("F2.x = {0}", f2.x);
Console.WriteLine("f1.x = {0}", f1.x);
return 0;
12/19/21 } GRNICA 33
}
• In contrast, reference types are allocated on the garbage-collected
heap.
• These entities stay in memory until the .NET garbage collector
destroys them.
• Assignment of reference types results in a new reference to the
same object in the memory.
using System;
// Classes are always reference types.
class FOO
{
public int x, y;
}
12/19/21 GRNICA 34
class ValRefClass
{
public static int Main(string[] args)
{
FOO f1 = new FOO();
f1.x = 100;
f1.y = 100;
Console.WriteLine("-> Assigning f2 to f1\n");
FOO f2 = f1;
//Here is F1.
Console.WriteLine("F1.x = {0}", f1.x);
Console.WriteLine("F1.y = {0}", f1.y);
//Here is F2.
Console.WriteLine("F2.x = {0}", f2.x);
Console.WriteLine("F2.y = {0}", f2.y);
//Change f2.x. This will not change f1.x
Console.WriteLine("->Changing f2.x to 900");
f2.x=900;
//Print again.
Console.WriteLine("F2.x = {0}", f2.x);
Console.WriteLine("f1.x = {0}", f1.x);
return 0;
12/19/21 } GRNICA 35
}
Value Types Containing Reference Types
• Assume you have the following reference (class) type:
class ShapeInfo
{
public string infoString;
public ShapeInfo(string info)
{ infoString = info; }
}
12/19/21 GRNICA 36
struct MyRectangle
{
// The MyRectangle structure contains a reference type member.
public ShapeInfo rectInfo; //Refrence type.
public int top, left, bottom, right; //Value type.
public MyRectangle(string info)
{
rectInfo = new ShapeInfo(info);
top = left = 10;
bottom = right = 100;
}
}
12/19/21 GRNICA 37
class reference1
{
static void Main(string[] args)
{
// Create the first MyRectangle.
Console.WriteLine("-> Creating r1");
MyRectangle r1 = new MyRectangle("This is my first rect");
// Print values
Console.WriteLine("-> Values after change:");
Console.WriteLine("-> r1.rectInfo.infoString: {0}", r1.rectInfo.infoString);
Console.WriteLine("-> r2.rectInfo.infoString: {0}", r2.rectInfo.infoString);
Console.WriteLine("-> r1.bottom: {0}", r1.bottom);
Console.WriteLine("-> r2.bottom: {0}", r2.bottom);
}
12/19/21 GRNICA 38
}
Value and Reference Types: Final Details
12/19/21 GRNICA 39
12/19/21 GRNICA 40
The Master Node: System.Object
• In C#, every data type (value or reference based) is ultimately
derived from a common base class: System.Object.
• The Object class defines a common polymorphic behavior for every
type in the .NET universe.
// Implicitly deriving from System.Object.
class HelloClass {...}
12/19/21 GRNICA 43
12/19/21 GRNICA 44
// Create some objects and exercise the inherited System.Object methods. Derived classes override this
using System; method to return a string
class ObjTest representing the values of its
{ internal state data.
GetType() retrieves a
public static
System.Type intwhich
object, Main(string[] args)
{ a property named
defines
BaseType. // Make an instance of ObjTest.
ObjTest c1 = new ObjTest();
// Pump
The default behavior info to is
of Equals() console.
Console.WriteLine("ToString:
to compare two objects' variables {0} ", c1.ToString());
Console.WriteLine("Hash
using reference semantics not value code: {0} ", c1.GetHashCode());
semantics. Console.WriteLine("Base class: {0} ", c1.GetType().BaseType);
// Make some other references to c1.
ObjTest c2 = c1;
object o = c2;
// Are all 3 instances pointing to the same object in memory?
if(o.Equals(c1) && c2.Equals(o))
Returns an integer that
Console.WriteLine("Same instance!");
identifies a specific object
return 0; instance.
}
}
12/19/21 GRNICA 45
Overriding Some Default Behaviors of System.Object
• Although the System.Object can be used in number of cases, it is
quite common for our custom types to override some of these
inherited methods.
• System.Object defines a number of virtual methods (such as
ToString() and Equals()).
• However, if we want to build a custom implementation of these
virtual members for a derived type, we make use of the C#
"override" keyword.
12/19/21 GRNICA 46
• To illustrate, assume we have a Person class that defines some state data
representing an individual's name, social security number, and age:
12/19/21 50
// Return a hash code based on the person's SSN.
public override int GetHashCode()
{
return SSN.GetHashCode();
}
12/19/21 GRNICA 51
// Make a few people and play with the overridden Object methods.
public static int Main(string[] args)
{
...
//NOTE: We want these to be identical to test the Equals() method.
Person p1 = new Person("Fred", "Jones", "222-22-2222", 98);
Person p2 = new Person("Fred", "Jones", "222-22-2222", 98);
12/19/21 GRNICA 53
The System Data Types (and C# Aliases)
12/19/21 GRNICA 54
12/19/21 GRNICA 55
12/19/21 GRNICA 56
• Although C# defines a number of data types, only a subset of the
whole are compliant with the rules of the CLS.
• When you build custom types that must work seamlessly across all
languages, you must stick to this well-defined subset.
12/19/21 GRNICA 57
Experimenting with the System Data Types
• The only purpose of System.ValueType is to override the virtual
methods defined by System.Object to work with value-based versus
reference-based semantics.
// The test succeeds! The two instances contain the same value.
if(intA = = intB)
Console.WriteLine("Same Value");
12/19/21 GRNICA 58
Basic Numerical Members
• The numerical types support MaxValue and MinValue properties
that provide information regarding the minimum and maximum
value
a given
using type can hold.
System;
class MyDataTypes
{
public static int Main(string[] args)
{
UInt16 myUInt16 = 30000;
Console.WriteLine("Max for an UInt16 is :{0}", UInt16.MaxValue);
Console.WriteLine("Min for an UInt16 is :{0}", UInt16.MinValue);
Console.WriteLine("Value is: {0}", myUInt16);
Console.WriteLine("I am a: {0}",myUInt16.GetType().ToString());
//Now in System.UInt16 shorthand( eg. a ushort).
ushort myOtherUInt16 = 12000;
Console.WriteLine("Max for an UInt16 is: {0}", ushort.MaxValue);
Console.WriteLine("Min for an UInt16 is: {0}", ushort.MinValue);
Console.WriteLine("Value is: {0}", myOtherUInt16);
Console.WriteLine("I am a: {0}", myOtherUInt16.GetType().ToString());
return 0;
}
} 12/19/21 GRNICA 59
using System;
class MyDataTypes
{
public static int Main(string[] args)
{
UInt16 myUInt16 = 30000;
Console.WriteLine("Max for an UInt16 is :{0}", UInt16.MaxValue);
Console.WriteLine("Min for an UInt16 is :{0}", UInt16.MinValue);
Console.WriteLine("Value is: {0}", myUInt16);
Console.WriteLine("I am a: {0}",myUInt16.GetType().ToString());
//Now in System.UInt16 shorthand( eg. a ushort).
ushort myOtherUInt16 = 12000;
Console.WriteLine("Max for an UInt16 is: {0}", ushort.MaxValue);
Console.WriteLine("Min for an UInt16 is: {0}", ushort.MinValue);
Console.WriteLine("Value is: {0}", myOtherUInt16);
Console.WriteLine("I am a: {0}", myOtherUInt16.GetType().ToString());
12/19/21 GRNICA 61
Members of System.Char
• .NET offers a very simplified view of string management.
• All .NET-aware languages map textual data to the same underlying
types (System.String and System.Char), both are Unicode.
• Using the static methods of System.Char, you are able to determine
if a given character is numerical, alphabetical, a point of punctuation,
or whatnot.
12/19/21 GRNICA 62
Console.WriteLine("-> char.IsDigit('K'): {0}", char.IsDigit('K'));
Console.WriteLine("-> char.IsDigit('9'): {0}", char.IsDigit('9'));
Console.WriteLine("-> char.IsLetter('10', 1): {0}", char.IsLetter("10", 1));
Console.WriteLine("-> char.IsLetter('p'): {0}", char.IsLetter('p'));
Console.WriteLine("-> char.IsWhiteSpace('Hello There', 5): {0}",
char.IsWhiteSpace("Hello There", 5));
Console.WriteLine("-> char.IsWhiteSpace('Hello There', 6): {0}",
char.IsWhiteSpace("Hello There", 6));
Console.WriteLine("-> char.IsLetterOrDigit('?'): {0}",
char.IsLetterOrDigit('?'));
Console.WriteLine("-> char.IsPunctuation('!'): {0}",
char.IsPunctuation('!'));
Console.WriteLine("-> char.IsPunctuation('>'): {0}",
char.IsPunctuation('>'));
Console.WriteLine("-> char.IsPunctuation(','): {0}",
char.IsPunctuation(','));
12/19/21 GRNICA 63
Parsing Values from String Data
bool myBool = bool.Parse("True");
Console.WriteLine("-> Value of myBool: {0}", myBool);
12/19/21 GRNICA 64
Converting Between Value Types and Reference Types:
Boxing and Unboxing
• .NET defines the types into value-based and reference-based.
• Some times we need to represent a variable of one category as a
variable of the other category.
• C# provides a very simple mechanism to convert between value
types and reference types, termed as boxing.
//Make a simple value data point.
short s = 25;
12/19/21 GRNICA 67
Some Practical (Un)boxing Examples
• If you pass a value type into a method requiring an object parameter,
boxing occurs behind the curtains.
• If we wish to invoke members of the underlying value type, we will
be required to perform an explicit unboxing operation.
12/19/21 GRNICA 68
using System;
class Boxer
{
public static void UseThisObject(object o)
{
Console.WriteLine(o.GetType());
Console.WriteLine(o.ToString());
Console.WriteLine("Value of o is : {0}", o);
// Need to explicitly unbox to get at members of
// System.Int32. (GetTypeCode() returns a value
// representing the underlying "type of intrinsic type".
Console.WriteLine(((int)o).GetTypeCode());
}
static void Main(String[] args)
{
int x = 90;
UseThisObject(x);
}
}
12/19/21 GRNICA 69
Defining Program Constants
• C# offers the "const" keyword, to define variables with a fixed,
unalterable value.
• The value of a constant point of data is computed at compile time,
and therefore a constant member cannot be assigned to an object
reference (whose value is computed at runtime).
• Although it is possible to define local constants within a method
scope, a more beneficial use of const is to create classlevel constant
definitions.
12/19/21 GRNICA 70
//some const data.
using System;
class MyConstants
{
//when accessed by another type, these constants must be referenced
// via the fully qualified name.
public const int myIntConst = 5;
public const string myStringConst = "I'am a const";
public static void Main()
{
//scoped constant.
const string localConst = "I am a rock, I am an island";
//use const data
Console.WriteLine("myIntConst = {0} \n myStringConst = {1}",
myIntConst, myStringConst);
Console.WriteLine("Local constant: {0}", localConst);
}
}
12/19/21 GRNICA 71
• If we create a utility class that contains nothing but constant data,
we may wish to define a private constructor.
• In this way, we ensure that the object user cannot make an instance
of our class.
// Private constructors prevent the creation of a given type.
class MyConstants
{
public const int myIntConst = 5;
public const string myStringConst = "I'm a const";
// Don't let the user make this class,
// as its only purpose is to define constant values.
private MyConstants(){ }
}
12/19/21 GRNICA 72
• The same result can be achieved by marking our "constant-only
class" as an abstract type.
12/19/21 GRNICA 73
Referencing Constant Data Across Types
• If we have moved our constant points of data into a new class
definition, how are they accessed from within another type?
• If we attempt to simply reference them by their unqualified name
(myIntConstant, myStringConstant) you will be issued a compiler
error.
• The reason is that under C#, global points of data are not allowed.
• Thus, any time we wish to access a constant defined outside of the
defining class, we must make use of the fully-qualified name.
12/19/21 GRNICA 74
public static void Main()
{
const string localConst = "I am a rock, I am an island";
// Use const data.
Console.WriteLine("myIntConst = {0}\nmyStringConst =
{1}\nLocalConst = {2}", MyConstants.myIntConst,
MyConstants.myStringConst, localConst);
}
12/19/21 GRNICA 75
// Private constructors prevent the creation of a given type.
using System;
class MyConstants
{
public const int myIntConst = 5;
public const string myStringConst = "I'm a const";
}
class Constants
{
public static void Main()
{
const string localConst = "I am a rock, I am an island";
Console.WriteLine("myIntConst = {0}\nmyStringConst =
{1}\nLocalConst = {2}",
MyConstants.myIntConst,MyConstants.myStringConst,localConst);
}
}
12/19/21 GRNICA 76
C# Iteration Constructs
• C# provides the following four iteration constructs:
• for loop
• foreach/in loop
• while loop
• do/while loop
12/19/21 GRNICA 77
The for loop
• We are able to specify how many times a block of code repeats
itself, as well as the terminating condition.
12/19/21 GRNICA 78
The foreach/in Loop
• The C# foreach keyword allows you to iterate over all items within
an array, without the need to test for the array’s upper limit.
• Here are two examples using foreach, one to traverse an array of
strings and the other to traverse an array of integers:
// Iterate array items using foreach.
static void Main(string[] args)
{
string[] books = {"Complex Algorithms",
"Do you Remember Classic COM?",
"C# and the .NET Platform"};
foreach (string s in books)
Console.WriteLine(s);
12/19/21 GRNICA 81
C# Control Flow Constructs
• C# defines two simple constructs to alter the flow of our program,
based on various contingencies:
• The if/else statement
• The switch statement
The if/else Statement
• The if/else statement in C# operates only on Boolean expressions,
not ad hoc values such as –1, 0.
12/19/21 GRNICA 82
The Switch Statement
• The switch statement allows you to handle program flow based on a
predefined set of choices.
12/19/21 GRNICA 83
// Switch on a numerical value.
static void Main(string[] args)
{
Console.WriteLine("1 [C#], 2 [VB]");
Console.Write("Please pick your language preference: ");
string langChoice = Console.ReadLine();
int n = int.Parse(langChoice);
switch (n)
{
case 1:
Console.WriteLine("Good choice, C# is a fine language.");
break;
case 2:
Console.WriteLine("VB .NET: OOP, multithreading, and more!");
break;
default:
Console.WriteLine("Well...good luck with that!");
break;
}
}
12/19/21 GRNICA 84
The Complete Set of C# Operators
12/19/21 GRNICA 85
Defining Custom Class Methods
• For defining custom class methods, every method we implement
must be a member of a class or struct.
• Like Main(), our custom methods may or may not take parameters,
may or may not return values.
• Also custom methods may be declared nonstatic (instance-level) or
static (class-level) entities.
12/19/21 GRNICA 86
Method Access Modifiers
• A method must specify its level of accessibility.
• C# offers the following method access modifiers.
12/19/21 GRNICA 87
Here are the implications of each accessibility keyword:
12/19/21 GRNICA 88
// Two public methods, each using an internal helper function.
using System;
class Teenager
{
// The System.Random type generates random numbers.
private Random r = new Random();
public string Complain()
{
string[] messages = new string[5]{ "Do I have to?",
"He started it!", "I'm too tired...",
"I hate school!", "You are sooo wrong." };
return messages[GetRandomNumber(5)];
}
12/19/21 GRNICA 90
Understanding Static Methods
• When a method is marked with the "static" keyword, it may be
called directly from the class level, and does not require an object
variable.
• For this very reason, Main() is declared static to allow the runtime
to
invoke this function without needing to allocate a new instance of
the defining class.
• We do not invoke the WriteLine() method from the object level:
12/19/21 GRNICA 91
using System;
class Teenager
{
private static Random r = new Random();
private static int GetRandomNumber(short upperLimit)
{
return r.Next(upperLimit);
}
12/19/21 98
The Default Parameter-Passing Behavior
• The default manner in which a parameter is sent into a function is by
value.
// Arguments are passed by value by default.
public static int Add(int x, int y)
{
int ans = x + y;
// Caller will not see these changes as you are modifying a copy of the
// original data.
x = 10000;
y = 88888;
return ans;
}
• The values of x and y remain same before and after the call to Add().
12/19/21 100
The C# "out" Keyword
class Program
{
public static void Add(int x, int y,out int ans)
{
ans = x + y;
//return ans;
}
static void Main(string[] args)
{
// No need to assign before use when a variable is used
int ans;
Add(9, 9, out ans);
Console.WriteLine("Answer is : {0}", ans);
}
}
• Calling a method with output parameters also requires the use of the
"out" keyword.
• C# out keyword does serve a very useful purpose: it allows the caller
12/19/21 101
to obtain multiple return values from a single method invocation.
class Program
{
// Returning multiple output parameters.
public static void FillTheseValues(out int a, out string b, out bool c)
{
a = 9;
b = "Enjoy your string.";
c = true;
}
static void Main(string[] args)
{
int i;
string str;
bool b;
FillTheseValues(out i, out str, out b);
Console.WriteLine("Int is: {0}", i);
Console.WriteLine("String is: {0}", str);
Console.WriteLine("Boolean is: {0}", b);
}
}
12/19/21 102
The C# "ref" Keyword
• Reference parameters are necessary when we wish to allow a method
to operate on various data points declared in the caller’s scope.
class Program
{
public static void SwapStrings(ref string s1, ref string s2)
{
string tempStr = s1;
s1 = s2;
s2 = tempStr;
}
static void Main(string[] args)
{
string s = "First string";
string s2 = "My other string";
Console.WriteLine("Before: {0}, {1} ", s, s2);
SwapStrings(ref s, ref s2);
Console.WriteLine("After: {0}, {1} ", s, s2);
}
12/19/21 103
}
The distinction between output and reference parameters:
• Output parameters do not need to be initialized before they are
passed to the method.
• Reference parameters must be initialized before they are passed to
the method.
12/19/21 104
The C# “params” Keyword
• The params keyword allows to create a method that may be sent to a
set of identically typed arguments as a single logical parameter.
class Program
{
// Return average of 'some number' of doubles.
static double CalculateAverage(params double[] values)
{
double sum = 0;
for (int i = 0; i < values.Length; i++)
sum += values[i];
return (sum / values.Length);
}
static void Main(string[] args)
{
// Pass in a comma-delimited list of doubles...
double average;
average = CalculateAverage(4.0, 3.2, 5.7);
Console.WriteLine("Average of 4.0, 3.2, 5.7 is: {0}",average);
// ...or pass an array of doubles.
double[] data = { 4.0, 3.2, 5.7 };
average = CalculateAverage(data);
Console.WriteLine("Average of data is: {0}", average);
12/19/21
} 105
}
Passing Reference Types by Value
}
using System;
class second_large
{
public static void Main()
{
int[] a = new int[10];
Console.WriteLine("Enter the array size:");
int n = int.Parse(Console.ReadLine());
Console.WriteLine("Enter the array elements:");
for (int i = 0; i < n; i++)
a[i] = int.Parse(Console.ReadLine());
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (a[i] < a[j])
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
Console.WriteLine("The Second largest number in an array is" + a[n - 2]);
} 12/19/21 GRNICA 115
115
}
using System;
class matrix_multi
{
public static void Main()
{
int [,] a = new int[3,3];
int [,] b = new int[3,3];
int [,] c = new int[3,3];
if (m1 == n2)
{
Console.WriteLine("Enter the Matrix A elements:");
for (int i = 0; i < m1; i++)
for (int j = 0; j < n1; j++)
a[i, j] = int.Parse(Console.ReadLine());
12/19/21 GRNICA 116
116
Console.WriteLine("Enter the Matrix B elements:");
for (int i = 0; i < m2; i++)
for (int j = 0; j < n2; j++)
b[i, j] = int.Parse(Console.ReadLine());
Console.WriteLine("The Matrix A is:");
for (int i = 0; i < m1; i++)
{
for (int j = 0; j < n1; j++)
{
Console.Write(a[i, j] + "\t");
}
Console.WriteLine();
}
}
}
} 12/19/21 GRNICA 118
118
• The second type of multidimensional array is termed a jagged
array.
• Jagged arrays contain some number of inner arrays, each of which
may have a unique upper limit.
}
}
12/19/21 GRNICA 121
The System.Array Base Class
• Every .NET array you create is automatically derived from
System.Array. This class defines a number of helpful methods that
make working with arrays much more palatable.
• Also note that verbatim strings can be used to preserve white space
for strings that flow over multiple lines:
// White space is preserved with verbatim strings.
string myLongString = @"This is a very
very
very
long string";
Console.WriteLine(myLongString);
12/19/21 GRNICA 130
Using System.Text.StringBuilder
• While the string type is perfect when you wish to represent basic
string variables (first name, SSN, etc.), it can be inefficient if you are
building a program that makes heavy use of textual data.
• The value of a string cannot be modified once established. C# strings
are immutable.
• If we examine the methods of System.String, we notice that the
methods that seem to internally modify a string, in fact return a
modified copy of the original string.
enum EmpType
{
Manager = 10,
Grunt = 1,
Contractor = 100,
VP = 9
} 12/19/21 GRNICA 135
• The storage type used for each item in an enumeration maps to a
System.Int32 by default. You are also free to change this to your
liking.
• If we want to set the underlying storage value of EmpType to be a
byte rather than an int, we can write as following:
// This time, EmpType maps to an underlying byte.
enum EmpType : byte
{
Manager = 10,
Grunt = 1,
Contractor = 100,
VP = 9
}
namespace MyApp
{
class ShapeTester
{
static void Main(string[] args)
{
Hexagon h = new Hexagon();
Circle c = new Circle();
Square s = new Square();
}
}
}
12/19/21 148
A Type’s Fully Qualified Name
• It is not required to make use of the C# using keyword when
declaring a type defined in an external namespace, rather fully
qualified name of the type could be used.
// Note we are not 'using' MyShapes anymore.
using System;
namespace MyApp
{
class ShapeTester
{
static void Main(string[] args)
{
MyShapes.Hexagon h = new MyShapes.Hexagon();
MyShapes.Circle c = new MyShapes.Circle();
MyShapes.Square s = new MyShapes.Square();
}
}
} 12/19/21 149
// Another shapes namespace...
using System;
namespace My3DShapes
{
// 3D Circle class.
class Circle{ }
// 3D Hexagon class
class Hexagon{ }
// 3D Square class
class Square{ }
}
12/19/21 150
// Ambiguities abound!
using System;
using MyShapes;
using My3DShapes;
namespace MyApp
{
class ShapeTester
{
static void Main(string[] args)
{
// Which namespace do I reference?
Hexagon h = new Hexagon(); // Compiler error!
Circle c = new Circle(); // Compiler error!
Square s = new Square(); // Compiler error!
}
}
}
12/19/21 151
// We have now resolved the ambiguity.
static void Main(string[] args)
{
My3DShapes.Hexagon h = new My3DShapes.Hexagon();
My3DShapes.Circle c = new My3DShapes.Circle();
MyShapes.Square s = new MyShapes.Square();
}
12/19/21 152
Defining using Aliases
• The C# using keyword can also be used to create an alias to a type’s fully
qualified name.
• When we do so, we are able to define a token that is substituted with the type’s
full
name
using at compile time.
System;
using MyShapes;
using My3DShapes;
// Resolve the ambiguity using a custom alias.
using The3DHexagon = My3DShapes.Hexagon;
namespace MyApp
{
class ShapeTester
{
static void Main(string[] args)
{
// This is really creating a My3DShapes.Hexagon type.
The3DHexagon h2 = new The3DHexagon();
...
}
12/19/21 153
}
}
• This alternative using syntax can also be used to create an alias to a
lengthy namespace.
12/19/21 154
using System.Runtime.Serialization.Formatters.Binary;
namespace MyApp
{
class ShapeTester
{
static void Main(string[] args)
{
BinaryFormatter b = new BinaryFormatter();
}
}
}
12/19/21 155
Creating Nested Namespaces
• Namespaces with in other namespaces can be defined.
• The .NET base class libraries do so in numerous places to provide
an even deeper level of type organization.
• If we wish to create a root namespace that contains the existing
My3DShapes namespace, we can update our code as follows:
// Nesting a namespace.
namespace Chapter3
{
namespace My3DShapes
{
// 3D Circle class.
class Circle{ }
// 3D Hexagon class
class Hexagon{ }
// 3D Square class
class Square{ }
12/19/21
} 156
}
• A nested namespace can be defined using the following compact
form:
// Nesting a namespace (take two).
namespace Chapter3.My3DShapes
{
// 3D Circle class.
class Circle{ }
// 3D Hexagon class
class Hexagon{ }
// 3D Square class
class Square{ }
}
12/19/21 157