Z` APPLICATIONS DEVELOPMENT AND EMERGING TECHNOLOGIES Compiled by: Elias A. Austria Aleta C. Fabregas 1 Applications Development and Emerging Technologies INSTRUCTIONAL MATERIAL General Overview The instructional materials Basic Topics of C# that will include control flow, iteration, methods, objects and classes, graphical user Interface, exception handling and files and streams. Advanced Topics of C# include assertions, collection classes, searching and sorting, regular expressions, threads, networking with sockets, and C# database connectivity. By completing this course, the student will be well equipped to work on small-scale industrial software projects. This course concludes with a presentation of the final case project which uses the full power of the language. It gives the better view developing application using C# program. It will provide guidelines and standards on how an application will be developed, tested, implemented and maintained. General Objectives After completion of this Instructional Material student should be able to: 1. Understand the basic and advanced topics of C# programming 2. Appreciate the Object-Oriented approach in C# Programming 3. Know the guidelines and standards of Developing Application Program 4. Develop an application program using C# Programming language 5. Learn the basic ways of planning, designing, developing, testing, implementing and maintaining the application program “Everybody in this country should learn how to program a computer… because it teaches you how to think” – Steve Jobs General Course Materials Watch: You can watch these YouTube link for more information about C# Programming Language https://www.youtube.com/watch?v=GhQdlIFylQ8 https://www.youtube.com/watch?v=wLg-XdAmrak Read: For your course guide, read the syllabus Application Development and Emerging Technology and the Instructional Materials. Activities/ Assessments: Make sure that you read and understand each module to answer the assessment activity at the end of each module. 2 Table of Contents Contents Module 1....................................................................................................................................8 What is C#?.............................................................................................................................9 .Net Architecture ................................................................................................................. 11 C# IDEs ............................................................................................................................... 12 Module 2.................................................................................................................................. 14 Program Structure .............................................................................................................. 15 Types and Variables........................................................................................................... 16 C# Variables ......................................................................................................................... 20 Constants .............................................................................................................................. 20 Predefined Data Types in C# ................................................................................................. 21 C# Operators....................................................................................................................... 22 Arithmetic Operators ......................................................................................................... 22 Relational Operators .......................................................................................................... 23 Logical Operators .............................................................................................................. 24 Bitwise Operators .............................................................................................................. 25 Assignment Operators ....................................................................................................... 26 Miscellaneous Operators ................................................................................................... 27 Operator Precedence in C# ................................................................................................ 28 Basic Input/Output in C# .................................................................................................... 30 Console Input .................................................................................................................... 30 Console Output.................................................................................................................. 30 Control Flow ........................................................................................................................ 33 Conditional Statement ....................................................................................................... 33 Iteration Statement ............................................................................................................ 38 Arrays................................................................................................................................... 42 Single-Dimensional Arrays................................................................................................ 42 Multidimensional Arrays ................................................................................................... 43 Jagged Arrays .................................................................................................................... 45 Module 3................................................................................................................................... 49 Object-Oriented Programming .......................................................................................... 50 Classes and Objects .......................................................................................................... 50 3 Multiple Class Declaration ................................................................................................. 55 Partial classes ..................................................................................................................... 56 Static classes ...................................................................................................................... 58 Creating and Accessing Class Component Library......................................................... 58 Constructor and Destructor ............................................................................................... 61 Static Constructor ............................................................................................................... 62 Destructors .......................................................................................................................... 63 Method Overloading ........................................................................................................... 64 Method Overriding .............................................................................................................. 65 Encapsulation ..................................................................................................................... 71 Why do we need Encapsulation ......................................................................................... 72 Encapsulation Using Accessors and Mutators .................................................................... 73 Encapsulation Using Properties ......................................................................................... 73 Read Only Property ........................................................................................................... 74 Write Only Property .......................................................................................................... 75 Inheritance........................................................................................................................... 75 Constructor in Inheritance .............................................................................................. 78 Virtual Methods ............................................................................................................... 79 Hiding Methods ............................................................................................................... 80 Abstraction .......................................................................................................................... 81 Abstract Classes ............................................................................................................. 82 Sealed Classes ............................................................................................................... 83 Interface ............................................................................................................................ 84 Polymorphism ..................................................................................................................... 85 Types of Polymorphism..................................................................................................... 85 Static or Compile Time Polymorphism .............................................................................. 86 Dynamic / Runtime Polymorphism .................................................................................... 87 Preventing Derived class from overriding virtual members ................................................ 89 Accessing Base class virtual member................................................................................. 90 Module 4................................................................................................................................... 96 What is WPF? ..................................................................................................................... 97 WPF Architecture.............................................................................................................. 97 Advantages ........................................................................................................................ 98 Features ............................................................................................................................. 98 4 Create a Simple Application .............................................................................................. 99 Change the name of MainWindow.xaml .......................................................................... 101 Add a TextBlock control ................................................................................................. 101 Customize the text in the text block ................................................................................. 102 Add radio buttons ............................................................................................................ 102 Add display text for each radio button ............................................................................. 104 Set a radio button to be checked by default ...................................................................... 104 Add the button control ..................................................................................................... 105 Add code to the display button ........................................................................................ 106 Debug and test the application ......................................................................................... 106 What is XAML? ................................................................................................................. 107 Basic XAML ................................................................................................................... 108 Events in XAML ............................................................................................................. 109 Basic Controls ................................................................................................................... 112 The TextBlock control ..................................................................................................... 112 The Label control ............................................................................................................ 114 The TextBox control........................................................................................................ 117 The Button control........................................................................................................... 121 The CheckBox control ..................................................................................................... 124 The RadioButton control ................................................................................................. 128 The PasswordBox control ................................................................................................ 131 Module 5................................................................................................................................. 134 What is ADO.Net? ............................................................................................................ 135 The DataSet Class ........................................................................................................... 135 The DataTable Class........................................................................................................ 138 The DataRow Class ......................................................................................................... 139 The DataAdapter Object .................................................................................................. 140 The DataReader Object ................................................................................................... 140 DbCommand and DbConnection Objects ........................................................................ 140 ADO.Net on C# ................................................................................................................. 141 Connecting to a database ................................................................................................. 141 Connection pools ............................................................................................................. 141 Why use "using" in code.................................................................................................. 142 Executing the Commands ................................................................................................ 143 5 Parameterizing the data ................................................................................................... 143 Reading the data returned ................................................................................................ 144 Adding data to the SQL Server ........................................................................................ 145 Catching the errors from SQL Server............................................................................... 145 Working example ............................................................................................................ 146 Exception Handling in C# ................................................................................................ 150 try..catch..finally.............................................................................................................. 150 Uncaught Exceptions ....................................................................................................... 151 Multiple Catch Blocks ..................................................................................................... 154 Catching all Exceptions ................................................................................................... 155 Throwing an Exception ................................................................................................... 156 Re-throwing an Exception ............................................................................................... 156 Standard Exceptions ........................................................................................................ 157 User-defined Exceptions .................................................................................................. 158 Design Guidelines ........................................................................................................... 158 Module 6................................................................................................................................. 160 What is an Application? .................................................................................................. 161 What Is Application Development? ................................................................................. 161 Identifying the Issues ....................................................................................................... 161 Various Software Testing Concepts ............................................................................... 163 Difference Between Test Plan And Test Strategy............................................................. 163 Test Plan........................................................................................................................ 163 Test Plan Document ........................................................................................................ 163 Contents of Test plan Document (IEEE-829 test plan structure)....................................... 164 Test Strategy ................................................................................................................. 164 Test Strategy Document .............................................................................................. 164 Test Plan Vs Test Strategy .......................................................................................... 169 Difference Between Test Case And Test Script................................................................ 170 Difference Between Test Scenario and Test Condition .................................................... 171 Difference Between Test Procedure and Test Suite .......................................................... 173 Unit Testing ....................................................................................................................... 174 What do you mean by a Unit test ? .................................................................................. 174 Why do we need Unit test? .............................................................................................. 175 Let us start the show – create your first Unit test (step by Step) ....................................... 175 6 MS Unit tests................................................................................................................... 176 Test class requirements .................................................................................................... 179 Test method requirements................................................................................................ 180 Writing first Unit Test method ......................................................................................... 180 Analyze your test results why it failed ............................................................................. 182 Correct the bug to make test pass ..................................................................................... 182 Rerun Test to check if it is working or not ....................................................................... 182 TDD(Test Driven Development) Implementation using Unit Testing in C# ..................... 183 Let’s Implement TDD using MS Unit Testing ................................................................. 184 7 Module 1 Overview: The module provides the fundamentals concepts of Java language as programming language and software based platform. It discusses the characteristics, history, components and the java editions Module Objectives: After successful completion of this module, you should be able to: • Discuss the fundamental concepts of C# programming language. • Know the history of C# programming language. • Understand the different features released with C# versions. 8 What is C#? C# is a strongly typed object-oriented programming language. C# is open source, simple, modern, flexible, and versatile. In this article, let’s learn what C# is, what C# can do, and how C# is different than C++ and other programming languages. A programming language on computer science is a language that is used to write software programs. C# is a programming language developed and launched by Microsoft in 2001. C# is a simple, modern, and object-oriented language that provides modern day developers flexibility and features to build software that will not only work today but will be applicable for years in the future. Key characteristics of C# language include: 1. 2. 3. 4. 5. 6. Modern and easy Fast and open source Cross platform Safe Versatile Evolving C# is modern and easy C# is a simple, modern, and an object-oriented programming language. The purpose of C# was to develop a programming language that is not only easy to learn but also supports modern day functionality for all kind of software development. If you look at the history of programming languages and their features, each programming language was designed for a specific purpose to solve a specific need at that time. C# language however was designed to keep business and enterprises needs in mind. C# language was designed for businesses to build all kinds of software by using one single programming language. C# provides functionality to support modern day software development. C# supports Web, Mobile, and app development needs. Some of the modern-day programming language features C# supports are generics, var types, auto initialization of types and collections, lambda expressions, dynamic programming, asynchronous programming, tuples, pattern matching, advanced debugging and exception handling, and more. C# language syntaxes are influenced from C++, Java, Pascal and few other languages that are easy to adopt. C# also avoids complexity and unstructured language features. C# is fast and open source C# is open source under the .NET Foundation, which is governed and run independently of Microsoft. C# language specifications, compilers, and related tools are open source projects on Github. While C# language feature design is lead by Microsoft, the open source community is very active in the language development and improvements. 9 C# is fast compare to several other high-level programming languages. C# 8 has many performance improvements. C# is cross platform C# is cross platform programming language. You can build .NET applications that can be deployed on Windows, Linux, and Mac platforms. C# apps can also be deployed in cloud and containers. C# is safe and efficient C# is a type safe language. C# does not allow type conversions that may lead to data loss or other problems. C# allows developers to write safe code. C# also focuses on writing efficient code. Here is a list of some of the key concepts in C# that helps write safe and efficient code. • • • • • • • Unsafe type casting is not allowed. Nullable and non-nullable types are supported in C#. Declare a readonly struct to express that a type is immutable and enables the compiler to save copies when using in parameters. Use a ref readonly return when the return value is a struct larger than IntPtr.Size and the storage lifetime is greater than the method returning the value. When the size of a readonly struct is bigger than IntPtr.Size, you should pass it as an in parameter for performance reasons. Never pass a struct as an in parameter unless it's declared with the readonly modifier because it may negatively affect performance and could lead to an obscure behavior. Use a ref struct, or a readonly ref struct such as Span<T> or ReadOnlySpan<T> to work with memory as a sequence of bytes. C# is versatile C# is a Swiss army knife. While most programming languages were designed for a specific purpose, C# was designed to do C#. We can use C# to build today’s modern software applications. C# can be used to develop all kind of applications including Windows client apps, components and libraries, services and APIs, Web applications, Mobile apps, cloud applications, and video games. Here is a list of types of applications C# can build, • • • • • • • • • • • Windows client applications Windows libraries and components Windows services Web applications Web services and Web API Native iOS and Android mobile apps Backend services Azure cloud applications and services Backend database using ML/Data tools Interoperability software such as Office, SharePoint, SQL Server and so on. Artificial Intelligence and Machine learning 10 • • • • Blockchains and distributed ledger technology including cryptocurrency Internet of Things (IoT) devices Gaming consoles and gaming systems Video games C# is evolving C# 8.0 is the latest version of C#. If you look at C# language history, C# is evolving faster than any other languages. Thanks to Microsoft and a strong community support. C# was initially designed to write Windows client applications but today, C# can do pretty much anything from console apps, cloud app, and modern machine learning software. .Net Architecture C# programs run on .NET, a virtual execution system called the common language runtime (CLR) and a set of class libraries. The CLR is the implementation by Microsoft of the common language infrastructure (CLI), an international standard. The CLI is the basis for creating execution and development environments in which languages and libraries work together seamlessly. Source code written in C# is compiled into an intermediate language (IL) that conforms to the CLI specification. The IL code and resources, such as bitmaps and strings, are stored in an assembly, typically with an extension of .dll. An assembly contains a manifest that provides information about the assembly's types, version, and culture. When the C# program is executed, the assembly is loaded into the CLR. The CLR performs Just-In-Time (JIT) compilation to convert the IL code to native machine instructions. The CLR provides other services related to automatic garbage collection, exception handling, and resource management. Code that's executed by the CLR is sometimes referred to as "managed code," in contrast to "unmanaged code," which is compiled into native machine language that targets a specific platform. Language interoperability is a key feature of .NET. IL code produced by the C# compiler conforms to the Common Type Specification (CTS). IL code generated from C# can interact with code that was generated from the .NET versions of F#, Visual Basic, C++, or any of more than 20 other CTS-compliant languages. A single assembly may contain multiple modules written in different .NET languages, and the types can reference each other as if they were written in the same language. In addition to the run time services, .NET also includes extensive libraries. These libraries support many different workloads. They're organized into namespaces that provide a wide variety of useful functionality for everything from file input and output to string manipulation to XML parsing, to web application frameworks to Windows Forms controls. The typical C# application uses the .NET class library extensively to handle common "plumbing" chores. 11 The following table summarizes the C# versions with year and features. Version Year Features 1999- Modern, Object Oriented, Simple, Flexible, Typesafe, Managed, 1.0 2002 Garbage Collection, Cross-platform 2.0 2005 Generics, Anonymous Method, Partial Class, Nullable Type 3.0 2008 LINQ, Lamda Expression, Extension Method, Anonymous Type, Var 4.0 2010 Named and Optional Parameters, Dynamic Binding 5.0 2012 Async Programming Compiler-as-a-service (Roslyn), Exception filters, Await in catch/finally blocks, Auto property initializers, Dictionary initializer, Default values for 6.0 2015 getter-only properties, Expression-bodied members. Null propagator, String interpolation, nameof operator Tuples, Out variables, Pattern matching, Deconstruction, Local functions, Digit separators, Binary literals, Ref returns and locals, 7.0 2017 Generalized async return types, Expression bodied constructors and finalizers, Expression bodied getters and setters, Throw can also be used as expression 7.1 2017 Async main, Default literal expressions, Inferred tuple element names Reference semantics with value types, Non-trailing named arguments, 7.2 2017 Leading underscores in numeric literals, private protected access modifier Accessing fixed fields without pinning, Reassigning ref local variables, 7.3 2018 Using initializers on stackalloc arrays, Using fixed statements with any type that supports a pattern, Using additional generic constraints Nullable reference types, Async streams, ranges and indices, default 8.0 2019 implementation of interface members, recursive patterns, switch expressions, target-type new expressions C# IDEs The easiest way to get started with C#, is to use an IDE. An IDE (Integrated Development Environment) is used to edit and compile code. Mostly, we use Visual Studio in coding applications that will be written in C#. C# applications uses .NET Framework, so it makes sense to use Visual Studio, as the program, the framework, and the language, are all created by Microsoft. 12 Course Materials: https://www.c-sharpcorner.com/article/what-is-c-sharp/ https://www.w3schools.com/cs/cs_getstarted.asp https://docs.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/ Activities/Assessments: 1. Make a research about the latest updates in C# on application development. 2. Determine the advantages of C# program as an application development program. 13 Module 2 Overview: This module gives the detailed description of the fundamental statements of C#, from data types, variables, constants, operators, input/output statements, conditional, looping, arrays and further manipulation of arrays. This module explains the simplicity of the C# program and uniqueness that is used as application development program nowadays. Module Objectives: After successful Completion of this module, you should be able to: • Know the parts of the C# program. • Learn and understand the basic structures and basic statements of the C# program. • Apply the learned C# statements to develop a simple application. 14 Program Structure The key organizational concepts in C# are programs, namespaces, types, members, and assemblies. Programs declare types, which contain members and can be organized into namespaces. Classes, structs, and interfaces are examples of types. Fields, methods, properties, and events are examples of members. When C# programs are compiled, they're physically packaged into assemblies. Assemblies typically have the file extension .exe or .dll, depending on whether they implement applications or libraries, respectively. As a small example, consider an assembly that contains the following code: The fully qualified name of this class is Acme.Collections.Stack. The class contains several members: a field named top, two methods named Push and Pop, and a nested class named Entry. The Entry class further contains three members: a field named next, a field named data, and a constructor. The Stack is a generic class. It has one type parameter, T that is replaced with a concrete type when it's used. 15 Assemblies contain executable code in the form of Intermediate Language (IL) instructions, and symbolic information in the form of metadata. Before it's executed, the Just-In-Time (JIT) compiler of .NET Common Language Runtime converts the IL code in an assembly to processor-specific code. Because an assembly is a self-describing unit of functionality containing both code and metadata, there's no need for #include directives and header files in C#. The public types and members contained in a particular assembly are made available in a C# program simply by referencing that assembly when compiling the program. For example, this program uses the Acme.Collections.Stack class from the acme.dll assembly: To compile this program, you would need to reference the assembly containing the stack class defined in the earlier example. C# programs can be stored in several source files. When a C# program is compiled, all of the source files are processed together, and the source files can freely reference each other. Conceptually, it's as if all the source files were concatenated into one large file before being processed. Forward declarations are never needed in C# because, with few exceptions, declaration order is insignificant. C# doesn't limit a source file to declaring only one public type nor does it require the name of the source file to match a type declared in the source file. Types and Variables There are two kinds of types in C#: value types and reference types. Variables of value types directly contain their data. Variables of reference types store references to their data, the latter being known as objects. With reference types, it's possible for two variables to reference the same object and possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it isn't possible for operations on one to affect the other (except for ref and out parameter variables). 16 An identifier is a variable name. An identifier is a sequence of unicode characters without any whitespace. An identifier may be a C# reserved word, if it's prefixed by @. Using a reserved word as an identifier can be useful when interacting with other languages. C#'s value types are further divided into simple types, enum types, struct types, nullable value types, and tuple value types. C#'s reference types are further divided into class types, interface types, array types, and delegate types. The following outline provides an overview of C#'s type system. • Value types o Simple types ▪ Signed integral: sbyte, short, int, long ▪ Unsigned integral: byte, ushort, uint, ulong ▪ Unicode characters: char, which represents a UTF-16 code unit ▪ IEEE binary floating-point: float, double ▪ High-precision decimal floating-point: decimal ▪ Boolean: bool, which represents Boolean values—values that are either true or false o Enum types ▪ User-defined types of the form enum E {...}. An enum type is a distinct type with named constants. Every enum type has an underlying type, which must be one of the eight integral types. The set of values of an enum type is the same as the set of values of the underlying type. o Struct types 17 ▪ • User-defined types of the form struct S {...} o Nullable value types ▪ Extensions of all other value types with a null value o Tuple value types ▪ User-defined types of the form (T1, T2, ...) Reference types o Class types ▪ Ultimate base class of all other types: object ▪ Unicode strings: string, which represents a sequence of UTF-16 code units ▪ User-defined types of the form class C {...} o Interface types ▪ User-defined types of the form interface I {...} o Array types ▪ Single-dimensional, multi-dimensional, and jagged. For example: int[], int[,], and int[][] o Delegate types ▪ User-defined types of the form delegate int D(...) C# programs use type declarations to create new types. A type declaration specifies the name and the members of the new type. Six of C#'s categories of types are userdefinable: class types, struct types, interface types, enum types, delegate types, and tuple value types. • • • • A class type defines a data structure that contains data members (fields) and function members (methods, properties, and others). Class types support single inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes. A struct type is similar to a class type in that it represents a structure with data members and function members. However, unlike classes, structs are value types and don't typically require heap allocation. Struct types don't support user-specified inheritance, and all struct types implicitly inherit from type object. An interface type defines a contract as a named set of public members. A class or struct that implements an interface must provide implementations of the interface's members. An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces. A delegate type represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are analogous to function types provided by functional languages. They're also similar to the concept of function pointers found in some other languages. Unlike function pointers, delegates are object-oriented and type-safe. The class, struct, interface, and delegate types all support generics, whereby they can be parameterized with other types. 18 C# supports single-dimensional and multi-dimensional arrays of any type. Unlike the types listed above, array types don't have to be declared before they can be used. Instead, array types are constructed by following a type name with square brackets. For example, int[] is a single-dimensional array of int, int[,] is a two-dimensional array of int, and int[][] is a single-dimensional array of single-dimensional arrays, or a "jagged" array, of int. Nullable types don't require a separate definition. For each non-nullable type T, there's a corresponding nullable type T?, which can hold an additional value, null. For instance, int? is a type that can hold any 32-bit integer or the value null, and string? is a type that can hold any string or the value null. C#'s type system is unified such that a value of any type can be treated as an object. Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Values of reference types are treated as objects simply by viewing the values as type object. Values of value types are treated as objects by performing boxing and unboxing operations. In the following example, an int value is converted to object and back again to int. When a value of a value type is assigned to an object reference, a "box" is allocated to hold the value. That box is an instance of a reference type, and the value is copied into that box. Conversely, when an object reference is cast to a value type, a check is made that the referenced object is a box of the correct value type. If the check succeeds, the value in the box is copied to the value type. C#'s unified type system effectively means that value types are treated as object references "on demand." Because of the unification, general-purpose libraries that use type object can be used with all types that derive from object, including both reference types and value types. There are several kinds of variables in C#, including fields, array elements, local variables, and parameters. Variables represent storage locations. Every variable has a type that determines what values can be stored in the variable, as shown below. • • • Non-nullable value type o A value of that exact type Nullable value type o A null value or a value of that exact type object o A null reference, a reference to an object of any reference type, or a reference to a boxed value of any value type 19 • • • • Class type o A null reference, a reference to an instance of that class type, or a reference to an instance of a class derived from that class type Interface type o A null reference, a reference to an instance of a class type that implements that interface type, or a reference to a boxed value of a value type that implements that interface type Array type o A null reference, a reference to an instance of that array type, or a reference to an instance of a compatible array type Delegate type o A null reference or a reference to an instance of a compatible delegate type C# Variables Variables are containers for storing data values. In C#, there are different types of variables (defined with different keywords), for example: • • • • • int - stores integers (whole numbers), without decimals, such as 123 or -123 double - stores floating point numbers, with decimals, such as 19.99 or -19.99 char - stores single characters, such as 'a' or 'B'. Char values are surrounded by single quotes string - stores text, such as "Hello World". String values are surrounded by double quotes bool - stores values with two states: true or false Syntax: Example: Constants You can add the const keyword if you don't want others (or yourself) to overwrite existing values (this will declare the variable as "constant", which means unchangeable and readonly). 20 Example: Predefined Data Types in C# C# includes some predefined value types and reference types. The following table lists predefined data types: Type Description Range Suffix byte sbyte short ushort int 8-bit unsigned integer 8-bit signed integer 16-bit signed integer 16-bit unsigned integer 32-bit signed integer uint long 32-bit unsigned integer 64-bit signed integer ulong 64-bit unsigned integer float 32-bit Single-precision floating point type 64-bit double-precision floating point type 128-bit decimal type for financial and monetary calculations double decimal char 16-bit single Unicode character bool object string 8-bit logical true/false value Base type of all other types. A sequence of Unicode characters 21 0 to 255 -128 to 127 -32,768 to 32,767 0 to 65,535 -2,147,483,648 to 2,147,483,647 0 to 4,294,967,295 u -9,223,372,036,854,775,808 l to 9,223,372,036,854,775,807 0 to ul 18,446,744,073,709,551,615 -3.402823e38 to f 3.402823e38 -1.79769313486232e308 to d 1.79769313486232e308 (+ or -)1.0 x 10e-28 m to 7.9 x 10e28 Any valid character, e.g. a,*, \x0058 (hex), or\u0058 (Unicode) True or False DateTime Represents date and time 0:00:00am 1/1/01 to 11:59:59pm 12/31/9999 C# Operators An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulations. C# has rich set of built-in operators and provides the following type of operators • Arithmetic Operators Relational Operators Logical Operators Bitwise Operators Assignment Operators Misc Operators • • • • • This tutorial explains the arithmetic, relational, logical, bitwise, assignment, and other operators one by one. Arithmetic Operators Following table shows all the arithmetic operators supported by C#. Assume variable A holds 10 and variable B holds 20 then − Operator + Description Adds two operands Example A + B = 30 22 - Subtracts second operand from the first A - B = -10 * Multiplies both operands A * B = 200 / Divides numerator by de-numerator B/A=2 % Modulus Operator and remainder of after an integer division B%A=0 ++ Increment operator increases integer value by one A++ = 11 -- Decrement operator decreases integer value by one A-- = 9 Relational Operators Following table shows all the relational operators supported by C#. Assume variable A holds 10 and variable B holds 20, then − Operator Description Example == Checks if the values of two operands are equal or not, if yes then condition becomes true. (A == B) is not true. != Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. (A != B) is true. > Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. (A > B) is not true. 23 < Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. (A < B) is true. >= Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. (A >= B) is not true. <= Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. (A <= B) is true. Logical Operators Following table shows all the logical operators supported by C#. Assume variable A holds Boolean value true and variable B holds Boolean value false, then − Operator Description Example && Called Logical AND operator. If both the operands are non zero then condition becomes true. (A && B) is false. || Called Logical OR Operator. If any of the two operands is non zero then condition becomes true. (A || B) is true. ! Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true then Logical NOT operator will make false. !(A && B) is true. 24 Bitwise Operators Bitwise operator works on bits and perform bit by bit operation. The truth tables for &, |, and ^ are as follows − p q p&q p|q p^q 0 0 0 0 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 1 Assume if A = 60; and B = 13; then in the binary format they are as follows − A = 0011 1100 B = 0000 1101 ------------------A&B = 0000 1100 A|B = 0011 1101 A^B = 0011 0001 ~A = 1100 0011 The Bitwise operators supported by C# are listed in the following table. Assume variable A holds 60 and variable B holds 13, then − Operator & Description Binary AND Operator copies a bit to the result if it exists in both operands. 25 Example (A & B) = 12, which is 0000 1100 | Binary OR Operator copies a bit if it exists in either operand. (A | B) = 61, which is 0011 1101 ^ Binary XOR Operator copies the bit if it is set in one operand but not both. (A ^ B) = 49, which is 0011 0001 Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. (~A ) = -61, which is 1100 0011 in 2's complement due to a signed binary number. << Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. A << 2 = 240, which is 1111 0000 >> Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. A >> 2 = 15, which is 0000 1111 ~ Assignment Operators There are following assignment operators supported by C# − Operator Description Example = Simple assignment operator, Assigns values from right side operands to left side operand C = A + B assigns value of A + B into C += Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand C += A is equivalent to C = C+A -= Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand C -= A is equivalent to C = C-A 26 *= Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand C *= A is equivalent to C = C*A /= Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand C /= A is equivalent to C = C/A %= Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand C %= A is equivalent to C = C%A <<= Left shift AND assignment operator C <<= 2 is same as C = C << 2 >>= Right shift AND assignment operator C >>= 2 is same as C = C >> 2 &= Bitwise AND assignment operator C &= 2 is same as C=C&2 ^= bitwise exclusive OR and assignment operator C ^= 2 is same as C=C^2 |= bitwise inclusive OR and assignment operator C |= 2 is same as C=C|2 Miscellaneous Operators There are few other important operators including sizeof, typeof and ? : supported by C#. Operator Description Example 27 sizeof() Returns the size of a data type. sizeof(int), returns 4. typeof() Returns the type of a class. typeof(StreamReader); Returns the address of an variable. &a; returns actual address of the variable. Pointer to a variable. *a; creates pointer named 'a' to a variable. Conditional Expression If Condition is true ? Then value X : Otherwise value Y Determines whether an object is of a certain type. If( Ford is Car) // checks if Ford is an object of the Car class. & * ?: is as Object obj = new StringReader("Hello"); Cast without raising an exception if the cast fails. StringReader r = obj as StringReader; Operator Precedence in C# Operator precedence determines the grouping of terms in an expression. This affects evaluation of an expression. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator. For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so the first evaluation takes place for 3*2 and then 7 is added into it. Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators are evaluated first. 28 Category Operator Associativity Postfix () [] -> . ++ - - Left to right Unary + - ! ~ ++ - - (type)* & sizeof Right to left Multiplicative */% Left to right Additive +- Left to right Shift << >> Left to right Relational < <= > >= Left to right Equality == != Left to right Bitwise AND & Left to right Bitwise XOR ^ Left to right Bitwise OR | Left to right Logical AND && Left to right Logical OR || Left to right Conditional ?: Right to left Assignment = += -= *= /= %=>>= <<= &= ^= |= Right to left 29 Comma , Left to right Basic Input/Output in C# Console Input The Console class allows using the Write () and the WriteLine () functions to display things on the screen. While the Console.Write () method is used to display something on the screen, the Console class provides the Read () method to get a value from the user. To use it, the name of a variable can be assigned to it. The syntax used is: variableName = Console. Read(); This simply means that, when the user types something and presses Enter, what the user had typed would be given (the word is assigned) to the variable specified on the left side of the assignment operator. Read() doesn’t always have to assign its value to a variable. For example, it can be used on its own line, which simply means that the user is expected to type something but the value typed by the user would not be used for any significant purpose. For example some versions of C# (even including Microsoft’s C# and Borland C#Builder) would display the DOS window briefly and disappear. You can use the Read() function to wait for the user to press any key in order to close the DOS window. Besides Read(), the Console class also provides the ReadLine() method. Like the WriteLine() member function, after performing its assignment, the ReadLine() method sends the caret to the next line. Otherwise, it plays the same role as the Read() function. string FirstName; Console.write(“Enter First Name: “); FirstName = console.ReadLine(); In C#, everything the user types is a string and the compiler would hardly analyze it without your explicit asking it to do so. Therefore, if you want to get a number from the user, first request a string. after getting the string, you must convert it to a number. To perform this conversion, each data type of the .NET Framework provides a mechanism called Parse. To use Parse(), type the data type, followed by a period, followed by Parse, and followed by parentheses. In the parentheses of Parse, type the string that you requested from the user. Console Output 30 Instead of using two Write() or a combination of Write() and WriteLine() to display data, you can convert a value to a string and display it directly. To do this, you can provide two strings to the Write() or WriteLine() and separate them with a comma: 1. The first part of the string provided to Write() or WriteLine() is the complete string that would display to the user. This first string itself can be made of different sections: (a) One section is a string in any way you want it to display (b) Another section is a number included between an opening curly bracket “{“and a closing curly bracket “}”.This combination of”{” and “}”is referred to as a, placeholder. You can put the placeholder anywhere inside of the string. The first placeholder must have number O. The second must have number 1, etc. With this technique, you can create the string anyway you like and use the placeholders anywhere inside of the string 2. The second part of the string provided to Write() or WriteLine() is the value that you want to display. It can be one value if you used only one placeholder with 0 in the first string. It’ you used different placeholders, you can then provide a different value for each one of them in this second part, separating the values with a comma Here are examples: As mentioned already, the numeric value typed in the curly brackets of the first part is an ordered number. If you want to display more than one value, provide each incremental value in its curly brackets. The syntax used is: write(“To Display {0} {l} {2} {n}, First, second, Third, nth); You can use the sections between a closing curly bracket and an opening curly bracket to create a meaningful sentence. 31 The System names pace provides a specific letter that you can use in the Write() or WriteLine()’s placeholder for each category of data to display. To format a value, in the placeholder of the variable or value, after the number, type a colon and one of the appropriate letter from the following table. If you are using ToStringO, then, in the parentheses of ToString(), you can include a specific letter or combination inside of double-quotes. The letters and their meanings are: 32 Control Flow Control flow (or alternatively, flow of control) refers to the order in which the individual statements, instructions or function calls of an imperative or a declarative program are executed or evaluated. Conditional Statement A statement that can be executed based on a condition is known as a “Conditional Statement”. If-Else Statement The if statement is used to check for a condition and based on it decide whether or not to execute a code block. The if code block is executed only if the condition is true otherwise further instruction or else block gets executed. You can write nested if blocks if required. Following diagram shows the basic flow of a default if-else statement. It is not mandatory to have an else block after an if block. The else statement is used to specify the code which has to be executed if the condition doesn't return true. 33 Let's see a practical implementation of if statement. using System; namespace Studytonight { public class Program { public static void Main(string[] args) { int i = 100; if(i > 0) { Console.WriteLine("Given number is positive!"); } else { Console.WriteLine("Given number is negative!"); } Console.ReadKey(); } } } Output: Given number is positive! Try running the above program by providing a negative value to i variable, the else code will get executed. 34 If….Else If…..Else Statement If we have to specify two conditions which are related to each other, we can use the else if statement to specify the second condition and its related code block. We can use multiple else if blocks to add multiple conditions but it requires atleast one if block at the beginning, we can't directly write else and else if statements without having any if block. using System; namespace Studytonight { public class Program { public static void Main(string[] args) { int i = 0; // Zero is neutral in nature if(i > 0) { Console.WriteLine("Given number is positive!"); } else if(i < 0) { Console.WriteLine("Given number is negative!"); } else { Console.WriteLine("Given number is neither positive nor negative!"); } Console.ReadKey(); } } } Output: Given number is neither positive nor negative! Switch Case Statement The switch statement executes only one statement from multiple given statements associated with conditions. If any condition returns true, then the code statements below it gets executed. Following diagram shows the basic flow of a switch statement. 35 Let's see the practical implementation of the switch statement, using System; namespace Studytonight { public class Program { public static void Main(string[] args) { Console.WriteLine("1.Additon\n2.Subtraction\n3.Division\nEnter your choice:"); int c = Convert.ToInt32(Console.ReadLine()); switch(c) { case 1: Console.WriteLine("\nAddition selected!"); break; case 2: Console.WriteLine("\nSubtraction selected!"); break; case 3: Console.WriteLine("\nDivision selected!"); break; default: Console.WriteLine("\nYour choice not found!"); break; } Console.ReadKey(); } 36 } } Output: 1.Additon 2.Subtraction 3.Division Enter your choice: 4 Your choice not found! As you can see in the above code example, if none of the case is matched, then default case will be executed. If your choice is 1 then the only case 1 will be executed and other cases will not execute not even the default case. The break statement is used to come out of any switch case, if we remove the break statements from all the case blocks, then after the execution of the case for which the condition is true, the default condition will also get executed. Goto Statement The goto statement is used to transfer the control from a loop or switch case to a specified label. It is also known as a jump statement. It is generally recommended to avoid using it as it makes the program more complex. In the following example, if the user is logged in then we have directly jumped our code to success label. using System; namespace Studytonight { public class Program { public static void Main(string[] args) { string user = "login"; if(user=="login") { goto success; } success: Console.WriteLine("Welcome to Studytonight!"); Console.ReadKey(); } } } Output: Welcome to Studytonight! 37 Iteration Statement An Iteration is just a fancy word for a loop. An Iteration statement will perform operations a set number of times until you tell it to stop, with a true or false value. Iteration statements also depend on an expression being evaluated until a that expression evaluates to false. This is called “loop termination criteria” and depends on Boolean values being evaluated. While statement The while statement is frequently used in code due to it’s simplicity and speed. In the example above I used a combination of do and while to create a do-while loop, but while can operate on it’s own. Let’s do the count to 10 with just a while loop and see how it works: static void Main() { int i = 0, limit = 10; while (i < limit) { Console.WriteLine("Count: " + i); i++; } } This loop is pretty much as simple as it gets. The while simply runs while the expression evaluates to true . In plain English: • • • While our value (i) is less than another value (limit) execute, Write out the value (i) Increment the value (i) This loop will repeat until the expression (i < limit) evaluates to false. If it is already set to false, nothing in the while loop will execute. Type the following in and run it: static void Main() { int i = 10, limit = 10; while (i < limit) { Console.WriteLine("Count: " + i); i++; } } 38 When you run this, you’ll notice nothing happens. This is because (i) is not less than (limit) so the loop never runs. This is ideal for most situations, but you may want your loop to run at least once, which brings us to the next loop. Do statement (with while) I used the do statement in the first example in combination with the while statment. Do executes a statement or block of statements until a specified expression evaluates to FALSE. You can use do without braces if it’s only a single statement: do Console.WriteLine("Count: " + i); while (i < limit); but if you need to execute more than one statement you’ll need to enclose them in braces: do { Console.WriteLine("Count: " + i); i++; } while (i < limit); The mechanics of this should be fairly obvious: in plain English we want to: • • • write a value (i) to the console increment the value repeat while that value is less than another (limit) This is pretty simple, but take a note of the order of operations with this loop. The thing to remember about a do-while loop such as the one above is this: A do-while loop will always execute then evaluate an expression to see if it needs to continue looping. The statement will always be executed at least once, while a while loop will only execute if a condition is evaluated as true. This is an important distinction. We can break out of a while loop early if needed: int i = 0, limit = 10; do { if (i == 7) { break; }else { Console.WriteLine("Count: " + i); } i++; } 39 while (i < limit); When you run this you will see the following output: Count: 0 Count: 1 Count: 2 Count: 3 Count: 4 Count: 5 Count: 6 This is because you put in a condition that evaluated whether i was 7 and if so, terminate the loop. This can come in pretty handy. You can also use goto, return and flow to break out of this loop as well. There are times where you may want to check for something in each iteration and if it happens, break out of it to correct it or stop the process. For Statement The for loop is a little more tricky to understand at first, but it performs the same function as a while loop. The for loop isn’t faster or any more powerful, but it is easier to construct and read so it’s mostly a programmer advantage (very important). Here’s an example of a for loop that counts to 10: public static void Main () { for (int i = 0; i < 10; i++) { Console.WriteLine(i); } } When you compile and run this it should look pretty familiar to you. The output is the same, but as you can see constructing the loop is easier and there is less code to look at. Let’s explain how it works in plain English: • • • test to see if our initial value (i) is less than ten if so, increment it and execute next expression write out the value (i) Foreach statement The foreach statement is a little different than for in that it repeats a group of statements for each element in an array, object or collection. It is used for reading those elements in the sequence defined by the foreach statement. 40 Here is an example of our count to 10 app with a foreach statement: public static void Main () { int[] ourArray = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 , 9 }; foreach (int i in ourArray) { System.Console.WriteLine(i); } } As you can see in this example it’s a little different because we’re creating an array on line 3 that we iterate though. Since this is an integer array we create the int(i) to represent the element of the array. Then we execute everything in the brackets each time a new element in the array is found. While there are new elements in i we will display them, then as soon as there are no more we exit from the loop. But this doesn’t just work on integer arrays, it works on all types of arrays and objects where you use an iterator. Here’s an example with strings: public static void Main () { string[] ourArray = new string[] { "C# Tutorials", "Python Tutorials", "Underwater Basket Weaving" }; foreach (string s in ourArray) { System.Console.WriteLine(s); } } Notice how the variable (s) is pulled from the array and displayed until there are no more in the array. This is a great way to iterate through arrays, lists, collections and objects. Note that you should generally only use this for read only operations. If you start messing with items of an array as it’s being traversed you get some pretty unexpected results. The foreach statement is great for working with data objects, and is extremely powerful and easy to use. 41 Arrays An array is a container object that holds a fixed number of values of a single type. Each item in an array is called an element, and each element is accessed by its numerical index. Array indices are always zero-based; the first element of the array is always indexed with 0. Obtaining an array is a two-step process. • • First, you must declare a variable of the desired array type Second, you must allocate the memory that will hold the array, using new, and assign it to the array variable So, let us see how can we declare arrays in different ways. An array has the following properties: • • • • • • • An array can be single-dimensional, multidimensional or jagged. The number of dimensions and the length of each dimension are established when the array instance is created. These values can't be changed during the lifetime of the instance. The default values of numeric array elements are set to zero, and reference elements are set to null. A jagged array is an array of arrays, and therefore its elements are reference types and are initialized to null. Arrays are zero indexed: an array with n elements is indexed from 0 to n-1. Array elements can be of any type, including an array type. Array types are reference types derived from the abstract base type Array. Since this type implements IEnumerable and IEnumerable<T>, you can use foreach iteration on all arrays in C#. Single-Dimensional Arrays You create a single-dimensional array using the new operator specifying the array element type and the number of elements. The following example declares an array of five integers: int[] array = new int[5]; This array contains the elements from array[0] to array[4]. The elements of the array are initialized to the default value of the element type, 0 for integers. 42 Arrays can store any element type you specify, such as the following example that declares an array of strings: string[] stringArray = new string[6]; Array Initialization You can initialize the elements of an array when you declare the array. The length specifier isn't needed because it's inferred by the number of elements in the initialization list. For example: int[] array1 = new int[] { 1, 3, 5, 7, 9 }; The following code shows a declaration of a string array where each array element is initialized by a name of a day: string[] weekDays = new string[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; You can avoid the new expression and the array type when you initialize an array upon declaration, as shown in the following code. This is called an implicitly typed array: int[] array2 = { 1, 3, 5, 7, 9 }; string[] weekDays2 = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; You can declare an array variable without creating it, but you must use the new operator when you assign a new array to this variable. For example: int[] array3; array3 = new int[] { 1, 3, 5, 7, 9 }; // OK //array3 = {1, 3, 5, 7, 9}; // Error Multidimensional Arrays Arrays can have more than one dimension. For example, the following declaration creates a twodimensional array of four rows and two columns. int[,] array = new int[4, 2]; The following declaration creates an array of three dimensions, 4, 2, and 3. int[,,] array1 = new int[4, 2, 3]; 43 Array Initialization You can initialize the array upon declaration, as is shown in the following example. // Two-dimensional array. int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // The same array with dimensions specified. int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // A similar array with string elements. string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" }, { "five", "six" } }; // Three-dimensional array. int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } }; // The same array with dimensions specified. int[,,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } }; // Accessing array elements. System.Console.WriteLine(array2D[0, 0]); System.Console.WriteLine(array2D[0, 1]); System.Console.WriteLine(array2D[1, 0]); System.Console.WriteLine(array2D[1, 1]); System.Console.WriteLine(array2D[3, 0]); System.Console.WriteLine(array2Db[1, 0]); System.Console.WriteLine(array3Da[1, 0, 1]); System.Console.WriteLine(array3D[1, 1, 2]); // Getting the total count of elements or the length of a given dimension. var allLength = array3D.Length; var total = 1; for (int i = 0; i < array3D.Rank; i++) { total *= array3D.GetLength(i); } System.Console.WriteLine("{0} equals {1}", allLength, total); You can also initialize the array without specifying the rank. int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; If you choose to declare an array variable without initialization, you must use the new operator to assign an array to the variable. The use of new is shown in the following example. 44 int[,] array5; array5 = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // OK //array5 = {{1,2}, {3,4}, {5,6}, {7,8}}; // Error The following example assigns a value to a particular array element. array5[2, 1] = 25; Similarly, the following example gets the value of a particular array element and assigns it to variable elementValue. int elementValue = array5[2, 1]; The following code example initializes the array elements to default values (except for jagged arrays). int[,] array6 = new int[10, 10]; Jagged Arrays A jagged array is an array whose elements are arrays, possibly of different sizes. A jagged array is sometimes called an "array of arrays." The following examples show how to declare, initialize, and access jagged arrays. The following is a declaration of a single-dimensional array that has three elements, each of which is a single-dimensional array of integers: int[][] jaggedArray = new int[3][]; Before you can use jaggedArray, its elements must be initialized. You can initialize the elements like this: jaggedArray[0] = new int[5]; jaggedArray[1] = new int[4]; jaggedArray[2] = new int[2]; Each of the elements is a single-dimensional array of integers. The first element is an array of 5 integers, the second is an array of 4 integers, and the third is an array of 2 integers. It is also possible to use initializers to fill the array elements with values, in which case you do not need the array size. For example: jaggedArray[0] = new int[] { 1, 3, 5, 7, 9 }; jaggedArray[1] = new int[] { 0, 2, 4, 6 }; jaggedArray[2] = new int[] { 11, 22 }; 45 You can also initialize the array upon declaration like this: int[][] jaggedArray2 = new int[][] { new int[] { 1, 3, 5, 7, 9 }, new int[] { 0, 2, 4, 6 }, new int[] { 11, 22 } }; You can use the following shorthand form. Notice that you cannot omit the new operator from the elements initialization because there is no default initialization for the elements: int[][] jaggedArray3 = { new int[] { 1, 3, 5, 7, 9 }, new int[] { 0, 2, 4, 6 }, new int[] { 11, 22 } }; A jagged array is an array of arrays, and therefore its elements are reference types and are initialized to null. You can access individual array elements like these examples: // Assign 77 to the second element ([1]) of the first array ([0]): jaggedArray3[0][1] = 77; // Assign 88 to the second element ([1]) of the third array ([2]): jaggedArray3[2][1] = 88; It's possible to mix jagged and multidimensional arrays. The following is a declaration and initialization of a single-dimensional jagged array that contains three two-dimensional array elements of different sizes. For more information, see Multidimensional Arrays. int[][,] jaggedArray4 = new int[3][,] { new int[,] { {1,3}, {5,7} }, new int[,] { {0,2}, {4,6}, {8,10} }, new int[,] { {11,22}, {99,88}, {0,9} } }; You can access individual elements as shown in this example, which displays the value of the element [1,0] of the first array (value 5): System.Console.Write("{0}", jaggedArray4[0][1, 0]); 46 The method Length returns the number of arrays contained in the jagged array. For example, assuming you have declared the previous array, this line: System.Console.WriteLine(jaggedArray4.Length); returns a value of 3. Example This example builds an array whose elements are themselves arrays. Each one of the array elements has a different size. class ArrayTest { static void Main() { // Declare the array of two elements. int[][] arr = new int[2][]; // Initialize the elements. arr[0] = new int[5] { 1, 3, 5, 7, 9 }; arr[1] = new int[4] { 2, 4, 6, 8 }; // Display the array elements. for (int i = 0; i < arr.Length; i++) { System.Console.Write("Element({0}): ", i); for (int j = 0; j < arr[i].Length; j++) { System.Console.Write("{0}{1}", arr[i][j], j == (arr[i].Length - 1) ? "" : " "); } System.Console.WriteLine(); } // Keep the console window open in debug mode. System.Console.WriteLine("Press any key to exit."); System.Console.ReadKey(); } } 47 Course Materials: https://docs.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/ https://www.w3schools.com/cs/cs_variables.asp https://www.tutorialsteacher.com/csharp/csharp-data-types https://ecomputernotes.com/csharp/csharp-libraries/console-input-output https://www.vskills.in/certification/tutorial/the-if-and-switch-statement/ https://www.studytonight.com/post/csharp-control-statements https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/ https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/singledimensional-arrays https://docs.microsoft.com/en-us/dotnet/csharp/programmingguide/arrays/multidimensional-arrays https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/jaggedarrays Activities/Assessments: 1. Write a C# program to check whether the given number is armstrong number or not.Armstrong Number in C#: A positive number is called armstrong number if it is equal to the sum of cubes of its digits for example 0, 1, 153, 370, 371, 407 etc. 48 Module 3 Overview: This module provides the detailed discussion with sample programs of the Object oriented approach of C# programming. The four general characteristics, Inheritance, Encapsulation, Abstraction and Polymorphism are presented with sample programs for better learning and application. Module Objectives: After successful Completion of this module, you should be able to: • Learn the basic concepts of Object-Oriented Programming • Discuss each characteristic of the Object-Oriented Programming • Know and understand each characteristic with examples • Apply the OOP concepts into application development program 49 Object-Oriented Programming Object-oriented programming (OOP) is the core ingredient of the .NET framework. OOP is so important that, before embarking on the road to .NET, you must understand its basic principles and terminology to write even a simple program. The fundamental idea behind OOP is to combine into a single unit both data and the methods that operate on that data; such units are called an object. All OOP languages provide mechanisms that help you implement the object-oriented model. They are encapsulation, inheritance, polymorphism and reusability. Let's now take a brief look at these concepts. Advantages of OOPS: • OOP offers easy to understand and a clear modular structure for programs. • Objects created for Object-Oriented Programs can be reused in other programs. Thus it saves significant development cost. • Large programs are difficult to write, but if the development and designing team follow OOPS concept then they can better design with minimum flaws. • It also enhances program modularity because every object exists independently. Comparison of OOPS with other programming styles with help of an Example Let's understand with example how OOPs is different than other programming approaches. Programming languages can be classified into 3 primary types 1. Unstructured Programming Languages: The most primitive of all programming languages having sequentially flow of control. Code is repeated through out the program 2. Structured Programming Languages: Has non-sequentially flow of control. Use of functions allows for re-use of code. 3. Object Oriented Programming: Combines Data & Action Together. Object-oriented programming (OOP) is the core ingredient of the .NET framework. OOP is so important that, before embarking on the road to .NET, you must understand its basic principles and terminology to write even a simple program. The fundamental idea behind OOP is to combine into a single unit both data and the methods that operate on that data; such units are called an object. All OOP languages provide mechanisms that help you implement the objectoriented model. They are encapsulation, inheritance, polymorphism and reusability. Let's now take a brief look at these concepts. Classes and Objects Classes are special kinds of templates from which you can create objects. Each object contains data and methods to manipulate and access that data. The class defines the data and the functionality that each object of that class can contain. A class declaration consists of a class header and body. The class header includes attributes, modifiers, and the class keyword. The class body encapsulates the members of the class, that are the data members and member functions. The syntax of a class declaration is as follows: Attributes accessibility modifiers class identifier: baselist { body } Attributes provide additional context to a class, like adjectives; for example the Serializable attribute. Accessibility is the visibility of the class. The default accessibility of a class is internal. 50 Private is the default accessibility of class members. The following table lists the accessibility keywords; Keyword Description public Public class is visible in the current and referencing assembly. private Visible inside current class. protected Visible inside current and derived class. Internal Visible inside containing assembly. Internal protected Visible inside containing assembly and descendent of thecurrent class. Modifiers refine the declaration of a class. The list of all modifiers defined in the table are as follows; Modifier Description sealed Class can't be inherited by a derived class. static Class contains only static members. unsafe The class that has some unsafe construct likes pointers. Abstract The instance of the class is not created if the Class is abstract. The baselist is the inherited class. By default, classes inherit from the System.Object type. A class can inherit and implement multiple interfaces but doesn't support multiple inheritances. Step-by-step Tutorial for Creating a Class 1. Open Visual Studio from start menu. 2. Go to "File" > "New" > "Project...", select "Console Application" in the right pane and provide the name "oops" for the project. 3. Then in the Solution Explorer, you will notice some files that are automatically created as, 51 4. You can also write your own code in the default program.cs file that is created but it is a good programming practice to create a new class. 5. For adding a new class, right-click over the project name (oops) in the Solution Explorer, then click "Add" > "Class". Give the name to the class "customer" as in the following; 52 When you open the customer.cs class. you will find some default-generated code as in the following, 1. using System; 2. using System.Collections.Generic; 3. using System.Linq; 4. using System.Text; 5. 6. namespace oops 7. { 8. class customer 9. { 10. } 11. } Note The C# console application project must require a single entry point Main () function that is already generated in the program class. For example if you add a new customer class and want to define one or more Main () entry points here then .NET will throw an error of multiple entry points. So it is advisable to delete or exclude the program.cs file from the solution. So here in this example the customer class defines fields such as CustID, Name and Address to hold information about a particular customer. It might also define some functionality that acts upon the data stored in these fields. 1. using System; 2. 3. namespace oops 4. { 5. class customer 6. { 7. // Member Variables 8. public int CustID; 9. public string Name; 10. public string Address; 11. 12. //constuctor for initializing fields 13. customer() 14. { 15. CustID=1101; 16. Name="Tom"; 17. Address="USA"; 18. } 19. 20. //method for displaying customer records (functionality) 21. public void displayData() 22. { 53 23. Console.WriteLine("Customer="+CustID); 24. Console.WriteLine("Name="+Name); 25. Console.WriteLine("Address="+Address); 26. } 27. // Code for entry point 28. } 29. } At line 9, we are defining a constructor of the customer class for initializing the class member fields. The constructor is a special function that is automatically called when the customer class object is created (instantiated). And at line 11 we are printing these fields to the console by creating a user defined method displayData(). You can then instantiate an object of this class to represent one specific customer, set the field value for that instance and use its functionality, as in: 1. class customer 2. { 3. // class members code 4. 5. //Entry point 6. static void Main(string[] args) 7. { 8. // object instantiation 9. customer obj = new customer(); 10. 11. //Method calling 12. obj.displayData(); 13. 14. //fields calling 15. Console.WriteLine(obj.CustID); 16. Console.WriteLine(obj.Name); 17. Console.WriteLine(obj.Address); 18. } 19. } Here you use the keyword new to declare the customer class instance. This keyword creates the object and initializes it. When you create an object of the customer class, the .NET framework IDE provides a special feature called Intellisense that provides access to all the class member fields and functions automatically. This feature is invoked when the "." operator is put right after the object, as in the following; 54 Image 1.1 Intellisense feature Normally, as the program grows in size and the code becomes more complex, the Intellisense feature increases the convenience for the programmer by showing all member fields, properties and functions. Multiple Class Declaration Sometimes circumstances require multiple classes to be declared in a single namespace. So in that case it is not mandatory to add a separate class to the solution, instead you can attach the new class into the existing program.cs or another one as in the following; 1. using System; 2. 3. namespace oops 4. { 5. class Program 6. { 7. 8. public void MainFunction() 9. { 10. Console.WriteLine("Main class"); 11. } 12. static void Main(string[] args) 13. { 14. //main class instance 15. Program obj = new Program(); 16. obj.MainFunction(); 17. 18. //other class instace 55 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. } demo dObj=new demo(); dObj.addition(); } } class demo { int x = 10; int y = 20; int z; public void addition() { z = x + y; Console.WriteLine("other class in Namespace"); Console.WriteLine(z); } } Here in this example, we are creating an extra class "demo" in the program.cs file at line 12 and finally we are instantiating the demo class with the program class inside the Main() entry in lines 6 to 11. So it doesn't matter how many classes we are defining in a single assembly. Partial classes Typically, a class will reside entirely in a single file. However, in situations where multiple developers need access to the same class, then having the class in multiple files can be beneficial. The partial keywords allow a class to span multiple source files. When compiled, the elements of the partial types are combined into a single assembly. There are some rules for defining a partial class as in the following; • • • A partial type must have the same accessibility. Each partial type is preceded with the "partial" keyword. If the partial type is sealed or abstract then the entire class will be sealed and abstract. In the following example we are adding two files, partialPart1.cs and partialPart2.cs, and declare a partial class, partialclassDemo, in both classes. partialPart1.cs 1. using System; 2. 3. namespace oops 4. { 5. public partial class partialclassDemo 6. { 56 7. public void method1() 8. { 9. Console.WriteLine("method from part1 class"); 10. } 11. } 12. } partialPart2.cs 1. using System; 2. 3. namespace oops 4. { 5. public partial class partialclassDemo 6. { 7. public void method2() 8. { 9. Console.WriteLine("method from part2 class"); 10. } 11. } 12. } And finally we are creating an instance of the partialclassDemo in the program.cs file as the following: Program.cs 1. using System; 2. 3. namespace oops 4. { 5. class Program 6. { 7. static void Main(string[] args) 8. { 9. //partial class instance 10. partialclassDemo obj = new partialclassDemo(); 11. obj.method1(); 12. obj.method2(); 13. } 14. } 15. } 57 Static classes A static class is declared using the "static" keyword. If the class is declared as static then the compiler never creates an instance of the class. All the member fields, properties and functions must be declared as static and they are accessed by the class name directly not by a class instance object. 1. using System; 2. 3. namespace oops 4. { 5. static class staticDemo 6. { 7. //static fields 8. static int x = 10, y; 9. 10. //static method 11. static void calcute() 12. { 13. y = x * x; 14. Console.WriteLine(y); 15. } 16. static void Main(string[] args) 17. { 18. //function calling directly 19. staticDemo.calcute(); 20. } 21. } 22. } Creating and Accessing Class Component Library .NET provides the capability of creating libraries (components) of a base application rather than an executable (".exe"). Instead the library project's final build version will be ".DLL" that can be referenced from other outside applications to expose its entire functionality. Step-by-step tutorial First create a class library based application as, 58 Then we are implementing a math class library that is responsible of calculating square root and the addition of two numbers as: 1. using System; 2. 3. namespace LibraryUtil 4. { 5. public class MathLib 6. { 7. public MathLib() { } 8. 9. public void calculareSum(int x, int y) 10. { 11. int z = x + y; 12. Console.WriteLine(z); 13. } 14. 15. public void calculareSqrt(double x) 16. { 17. double z = Math.Sqrt(x); 18. Console.WriteLine(z); 19. } 20. } 21. } 59 Build this code and you will notice that a DLL file was created, not an executable, in the root directory of the application (path = D:\temp\LibraryUtil\LibraryUtil\bin\Debug\ LibraryUtil.dll). Now create another console based application where you utilize all the class library's functionality. Then you have to add the class library dll file reference to access the declared class in the library dll. (Right-click on the Reference then "Add reference" then select the path of the dll file.) When you add the class library reference then you will notice in the Solution Explorer that a new LibraryUtil is added as in the following; Now add the namespace of the class library file in the console application and create the instance of the class declared in the library as in the following; 1. using System; 2. using LibraryUtil; // add library namespace 3. namespace oops 4. { 5. public class LibraryClass 6. { 7. static void Main() 8. { 9. //library class instance 10. MathLib obj = new MathLib(); 11. 12. //method populate 13. obj.calculareSum(2, 5); 14. obj.calculareSqrt(25); 15. } 16. } 17. } 60 Constructor and Destructor A constructor is a specialized function that is used to initialize fields. A constructor has the same name as the class. Instance constructors are invoked with the new operator and can't be called in the same manner as other member functions. There are some important rules pertaining to constructors as in the following; • • • • • • Classes with no constructor have an implicit constructor called the default constructor, that is parameterless. The default constructor assigns default values to fields. A public constructor allows an object to be created in the current assembly or referencing assembly. Only the extern modifier is permitted on the constructor. A constructor returns void but does not have an explicitly declared return type. A constructor can have zero or more parameters. Classes can have multiple constructors in the form of default, parameter or both. The following example shows one constructor for a customer class. 1. using System; 2. namespace oops 3. { 4. class customer 5. { 6. // Member Variables 7. public string Name; 8. 9. //constuctor for initializing fields 10. public customer(string fname, string lname) 11. { 12. Name= fname +" "+ lname; 13. } 14. //method for displaying customer records 15. public void AppendData() 16. { 17. Console.WriteLine(Name); 18. } 19. //Entry point 20. static void Main(string[] args) 21. { 22. // object instantiation 23. customer obj = new customer("Barack", "Obama"); 24. 25. //Method calling 26. obj.AppendData(); 27. } 28. } 29. } 61 Note The moment a new statement is executed, the default constructor is called. Static Constructor A constructor can be static. You create a static constructor to initialize static fields. Static constructors are not called explicitly with the new statement. They are called when the class is first referenced. There are some limitations of the static constructor as in the following; • • • Static constructors are parameterless. Static constructors can't be overloaded. There is no accessibility specified for Static constructors. In the following example the customer class has a static constructor that initializes the static field and this constructor is called when the class is referenced in the Main () at line 26 as in the following: 1. using System; 2. namespace oops 3. { 4. class customer 5. { 6. // Member Variables 7. static private int x; 8. 9. //constuctor for static initializing fields 10. static customer() 11. { 12. x = 10; 13. } 14. //method for get static field 15. static public void getData() 16. { 17. Console.WriteLine(x); 18. } 19. //Entry point 20. static void Main(string[] args) 21. { 22. //static Method calling 23. customer.getData(); 24. } 25. } 26. } 62 Destructors The purpose of the destructor method is to remove unused objects and resources. Destructors are not called directly in the source code but during garbage collection. Garbage collection is nondeterministic. A destructor is invoked at an undetermined moment. More precisely a programmer can't control its execution; rather it is called by the Finalize () method. Like a constructor, the destructor has the same name as the class except a destructor is prefixed with a tilde (~). There are some limitations of destructors as in the following; • • • • Destructors are parameterless. A Destructor can't be overloaded. Destructors are not inherited. Destructors can cause performance and efficiency implications. The following implements a destructor and dispose method. First of all we are initializing the fields via constructor, doing some calculations on that data and displaying it to the console. But at line 9 we are implementing the destructor that is calling a Dispose() method to release all the resources. 1. using System; 2. namespace oops 3. { 4. class customer 5. { 6. // Member Variables 7. public int x, y; 8. //constuctor for initializing fields 9. customer() 10. { 11. Console.WriteLine("Fields inititalized"); 12. x = 10; 13. } 14. //method for get field 15. public void getData() 16. { 17. y = x * x; 18. Console.WriteLine(y); 19. } 20. //method to release resource explicitly 21. public void Dispose() 22. { 23. Console.WriteLine("Fields cleaned"); 24. x = 0; 25. y = 0; 26. } 27. //destructor 28. ~customer() 29. { 63 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. } 42. } Dispose(); } //Entry point static void Main(string[] args) { //instance created customer obj = new customer(); obj.getData(); } At line 12 when the instance is created, fields are initialized but it is not necessary that at the same time the destructor is also called. Its calling is dependent on garbage collection. If you want to see the destructor being called into action then put a breakpoint (by F9) at line 10 and compile the application. The CLR indicates its execution at the end of the program by highlighting line 10 using the yellow color. Method Overloading Method overloading allows multiple implementations of the same function in a class. Overloaded methods share the same name but have a unique signature. The number of parameters, types of parameters or both must be different. A function can't be overloaded on the basis of a different return type alone. 1. using System; 2. namespace oops 3. { 4. class funOverload 5. { 6. public string name; 7. 8. //overloaded functions 9. public void setName(string last) 10. { 11. name = last; 12. } 13. 14. public void setName(string first, string last) 15. { 16. name = first + "" + last; 17. } 18. 19. public void setName(string first, string middle, string last) 64 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. } 35. } { name = first + "" + middle + "" + last; } //Entry point static void Main(string[] args) { funOverload obj = new funOverload(); obj.setName("barack"); obj.setName("barack "," obama "); obj.setName("barack ","hussian","obama"); } At lines 3, 4 and 5 we are defining three methods with the same name but with different parameters. In the Main (), the moment you create an instance of the class and call the functions setName() via obj at lines 7, 8 and 9 then intellisense will show three signatures automatically. Method Overriding Overriding can be defined as: being able to change or augment the behavior of methods in classes, known as overriding their logic; it is one of the most powerful aspects of Object Oriented Programming. Suppose you have a Phone, no please don’t suppose everyone has a phone today, although some people even have more than one. Okay leave it, so if you have phone: Then there must be ring facility in it: 65 Now your phone can be of any type, like it can be cellular, satellite or landline, these all types of phones will also have the same or a different functionality (based on their attribute). Now whenever you receive a call, the caller doesn’t know whether you have a cellular phone, landline phone or anything else, he/she just calls you and according to that call operation your phone rings. In the case of method overriding, your phone works as a class and the ring is the functionality. 66 Keywords in Method Overriding There are the following 3 types of keywords used in C# for method overriding: Virtual Keyword It tells the compiler that this method can be overridden by derived classes. 1. public virtual int myValue() 2. { 3. 4. 5. 6. } Override Keyword In the subclass, it tells the compiler that this method is overriding the same named method in the base class. 1. public override int myValue() 2. { 3. 4. 5. 6. } Base Keyword In the subclass, it calls the base class method for overriding functionality. 1. base.myValue(); 67 Method Overriding Example 1. using System; 2. using System.Collections.Generic; 3. using System.Linq; 4. using System.Text; 5. namespace Hello_Word 6. { 7. class baseClass 8. { 9. public virtual void Greetings() 10. { 11. Console.WriteLine("baseClass Saying Hello!"); 12. } 13. } 14. class subClass : baseClass 15. { 16. public override void Greetings() 17. { 18. base.Greetings(); 19. Console.WriteLine("subClass Saying Hello!"); 20. } 21. } 22. class Program 23. { 24. static void Main(string[] args) 25. { 26. baseClass obj1 = new subClass(); 27. obj1.Greetings(); 28. Console.ReadLine(); 29. } 30. } 31. } 68 An output window is showing that baseClass will get called first and then subclass. If we make certain changes in this code like: 1. base.Greetings(); 2. Console.WriteLine("subClass Saying Hello!"); // current scenario After making a few modifications as in the following: 1. Console.WriteLine("subClass Saying Hello!"); 2. base.Greetings(); // after modifications Now our output will be like this: If we remove "base.Greetings();" then the compiler will not call the baseclass as in the following: 1. using System; 2. using System.Collections.Generic; 3. using System.Linq; 4. using System.Text; 5. namespace Hello_Word 6. { 7. class baseClass 8. { 9. public virtual void Greetings() 10. { 11. Console.WriteLine("baseClass Saying Hello!"); 12. } 13. } 14. class subClass : baseClass 15. { 16. public override void Greetings() 17. { 18. Console.WriteLine("subClass Saying Hello!"); 69 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. } // base.Greetings(); } } class Program { static void Main(string[] args) { baseClass obj1 = new subClass(); obj1.Greetings(); Console.ReadLine(); } } Now making some other changes, like placing: 1. baseClass obj1 = new baseClass(); 2. obj1.Greetings(); Instead of: 1. baseClass obj1 = new subClass(); 2. obj1.Greetings(); Now let’s check the output window, what’s its showing now: 70 So as you are seeing that now its calling only the baseClass. So now I guess you will be a little closer to the method overriding functionality. Encapsulation Encapsulation is the mechanism that binds together the code and the data it manipulates, and keeps both safe from outside interference and misuse. In OOP, code and data may be combined in such a way that a self-contained box is created. When code and data are linked together in this way, an object is created and encapsulation exists. Within an object, code, data or both may be private or public to that object. Private code is known to and accessible only by another part of the object, that is private code or data may not be accessible by a piece of the program that exists outside the object. When the code and data is public, other portions of your program may access it even though it is defined within an object. 1. using System; 2. namespace oops 3. { 4. class Encapsulation 5. { 6. /// <summary> 7. /// Every member Variable and Function of the class are bind 8. /// with the Encapsulation class object only and safe with 9. /// the outside inference 10. /// </summary> 11. 12. // Encapsulation Begin 71 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. } 41. } int x; //class constructor public Encapsulation(int iX) { this.x = iX; } //calculating the square public void MySquare() { int Calc = x * x; Console.WriteLine(Calc); } // End of Encapsulation //Entry point static void Main(string[] args) { //instance created customer obj = new customer(20); obj. MySquare(); } Why do we need Encapsulation The need of encapsulation is to protect or prevent the code (data) from accidental corruption due to the silly little errors that we are all prone to make. In Object oriented programming data is treated as a critical element in the program development and data is packed closely to the functions that operate on it and protects it from accidental modification from outside functions. Encapsulation provides a way to protect data from accidental corruption. Rather than defining the data in the form of public, we can declare those fields as private. The Private data are manipulated indirectly by two ways. Let us see some example programs in C# to demonstrate Encapsulation by those two methods. The first method is using a pair of conventional accessor and mutator methods. Another one method is using a named property. Whatever be the method our aim is to use the data without any damage or change. 72 Encapsulation Using Accessors and Mutators Let us see an example of Department class. To manipulate the data in that class (String departname) we define an accessor (get method) and mutator (set method). 1. using system; 2. public class Department { 3. private string departname;....... 4. // Accessor. 5. public string GetDepartname() { 6. return departname; 7. } 8. // Mutator. 9. public void SetDepartname(string a) { 10. departname = a; 11. } 12. } Like the above way we can protect the private data from the outside world. Here we use two separate methods to assign and get the required data. 1. public static int Main(string[] args) { 2. Department d = new Department(); 3. d.SetDepartname("ELECTRONICS"); 4. Console.WriteLine("The Department is :" + d.GetDepartname()); 5. return 0; 6. } In the above example we can't access the private data departname from an object instance. We manipulate the data only using those two methods. Encapsulation Using Properties Properties are a new language feature introduced with C#. Only a few languages support this property. Properties in C# helps in protect a field in a class by reading and writing to it. The first method itself is good but Encapsulation can be accomplished much smoother with properties. Now let's see an example. 1. using system; 2. public class Department { 3. private string departname; 4. public string Departname { 5. get { 6. return departname; 7. } 73 8. set { 9. departname = value; 10. } 11. } 12. } 13. public class Departmentmain { 14. public static int Main(string[] args) { 15. Department d = new Department(); 16. d.departname = "Communication"; 17. Console.WriteLine("The Department is :{0}", d.Departname); 18. return 0; 19. } 20. } From the above example we see the usage of Encapsulation by using properties. The property has two accessor get and set. The get accessor returns the value of the some property field. The set accessor sets the value of the some property field with the contents of "value". Properties can be made read-only. This is accomplished by having only a get accessor in the property implementation. Read Only Property 1. using system; 2. public class ReadDepartment { 3. private string departname; 4. public ReadDepartment(string avalue) { 5. departname = avalue; 6. } 7. public string Departname { 8. get { 9. return departname; 10. } 11. } 12. } 13. public class ReadDepartmain { 14. public static int Main(string[] args) { 15. ReadDepartment d = new ReadDepartment("COMPUTERSCIENCE"); 16. Console.WriteLine("The Department is: {0}", d.Departname); 17. return 0; 18. } 19. } In the above example we see how to implement a read-only property. The class ReadDepartment has a Departname property that only implements a get accessor. It leaves out the set accessor. This particular class has a constructor, which accepts a string parameter. The Main method of the ReadDepartmain class creates a new object named d. The instantiation of the d object uses 74 the constructor of the ReadDepartment that takes a string parameter. Since the above program is read-only, we cannot set the value to the field departname and we only read or get the value of the data from the field. Properties can be made also Write-only. This is accomplished by having only a set accessor in the property implementation. Write Only Property 1. using system; 2. public class WriteDepartment { 3. private string departname; 4. public string Departname { 5. set { 6. departname = value; 7. Console.WriteLine("The Department is :{0}", departname); 8. } 9. } 10. } 11. public class WriteDepartmain { 12. public static int Main(string[] args) { 13. WriteDepartment d = new WriteDepartment(); 14. d.departname = "COMPUTERSCIENCE"; 15. return 0; 16. } 17. } In the above example we see how to implement a Write-only property. The class WriteDepartment has now has a Departname property that only implements a set accessor. It leaves out the get accessor. The set accessor method is varied a little by it prints the value of the departname after it is assigned. Inheritance Inheritance is the process by which one object can acquire the properties of another object. Inheritance is a "is a kind of" relationship and it supports the concept of classification in which an object needs only define those qualities that make it unique within the class. Inheritance involves a base class and a derived class. The derived class inherits from the base class and also can override inherited members as well as add new members to extend the base class. A base type represents the generalization, whereas a derived type represents a specification of an instance. Such as Employees that can have diverse types, such as hourly, salaried and temporary so in that case Employees is the general base class and hourly, salaried and temporary employee are specialized derived classes. Classes can inherit from a single class and one or more interfaces. When inheriting from a class, the derived class inherits the members including the code of the base class. The important point to remember is that Constructors and Destructors are not inherited from the base class. 75 The syntax of inheritance is as in the following; Class derivedClass : baseClass, Iterface1, Interface2 { body } For example we are defining two classes, Father and Child. You notice at line 7, we are implementing inheritance by using a colon (:); at this moment all the properties belonging to the Father Class is accessible to the Child class automatically. 1. using System; 2. namespace oops 3. { 4. //Base Class 5. public class Father 6. { 7. public void FatherMethod() 8. { 9. Console.WriteLine("this property belong to Father"); 10. } 11. } 12. 13. //Derived class 14. public class Child : Father 15. { 16. public void ChildMethod() 17. { 18. Console.WriteLine("this property belong to Child"); 19. } 20. } 21. class Inheritance 22. { 76 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. } 36. } //Entry point static void Main(string[] args) { Father fObj = new Father(); fObj.FatherMethod(); //Here Child object can access both class methods Child cObj = new Child(); cObj.FatherMethod(); cObj.ChildMethod(); } At line 11 , the Intellisense only shows the Father class functions but at line 15 to 16 the Child class object is able to access both class methods as in the following. We can create a class in the VB.Net language or another .NET supported language and can inherit them in a C# .Net class and vice versa. But a class developed in C++ or other unmanaged environment can't be inherited in .NET. Note Cross-language and multiple inheritance is not supported by .NET. Accessibility Accessibility sets the visibility of the member to outside assemblies or derived types. The following table describes member accessibility; Modifiers Outside Assembly Derived Class private No No public Yes Yes protected No No internal Yes ( this assembly only) Yes ( this assembly only) internal protected Yes ( this assembly only) Yes 77 Constructor in Inheritance Constructors in a base class are not inherited in a derived class. A derived class has a base portion and derived portion. The base portion initializes the base portion, and the constructor of the derived class initializes the derived portion. The following is the syntax of a constructor in inheritance; Accessibility modifier classname(parameterlist1) : base(parameterlist2) { body } So the base keyword refers to the base class constructor, while parameterlist2 determines which overloaded base class constructor is called. In the following example, the Child class's constructor calls the single-argument constructor of the base Father class; 1. using System; 2. namespace oops 3. { 4. //Base Class 5. public class Father 6. { 7. 8. //constructor 9. public Father() 10. { 11. Console.WriteLine("Father class constructor"); 12. } 13. 14. public void FatherMethod() 15. { 16. Console.WriteLine("this property belong to Father"); 17. } 18. } 19. 20. //Derived class 21. public class Child : Father 22. { 23. public Child() 24. : base() 25. { 26. Console.WriteLine("child class constructor"); 27. } 28. public void ChildMethod() 29. { 30. Console.WriteLine("this property belong to Child"); 31. } 32. } 78 33. class Inheritance 34. { 35. //Entry point 36. static void Main(string[] args) 37. { 38. //Here Child object can access both class methods 39. Child cObj = new Child(); 40. cObj.FatherMethod(); 41. cObj.ChildMethod(); 42. Console.ReadKey(); 43. } 44. } 45. } At line 4, we are defining a base Father Class constructor and in the derived class Child, at line 8 we are initializing it explicitly via base keyword. If we pass any parameter in the base class constructor then we have to provide them in the base block of the child class constructor. Virtual Methods By declaring a base class function as virtual, you allow the function to be overridden in any derived class. The idea behind a virtual function is to redefine the implementation of the base class method in the derived class as required. If a method is virtual in the base class then we have to provide the override keyword in the derived class. Neither member fields nor static functions can be declared as virtual. 1. using System; 2. namespace oops 3. { 4. class myBase 5. { 6. //virtual function 7. public virtual void VirtualMethod() 8. { 9. Console.WriteLine("virtual method defined in the base class"); 10. } 11. } 12. 13. class myDerived : myBase 14. { 15. // redifing the implementation of base class method 16. public override void VirtualMethod() 17. { 18. Console.WriteLine("virtual method defined in the Derive class"); 19. } 20. } 21. class virtualClass 79 22. { 23. static void Main(string[] args) 24. { 25. // class instance 26. new myDerived().VirtualMethod(); 27. Console.ReadKey(); 28. } 29. } 30. } Hiding Methods If a method with the same signature is declared in both base and derived classes, but the methods are not declared as virtual and overriden respectively, then the derived class version is said to hide the base class version. In most cases, you would want to override methods rather than hide them. Otherwise .NET automatically generates a warning. In the following example, we are defining a VirutalMethod() in the myBase class but not overriding it in the derived class, so in that case the compiler will generate a warning. The compiler will assume that you are hiding the base class method. So to overcome that problem, if you prefix the new keyword in the derived class method then the compiler will prefer the most derived version method. You can still access the base class method in the derived class by using the base keyword. 1. using System; 2. namespace oops 3. { 4. class myBase 5. { 6. //virtual function 7. public virtual void VirtualMethod() 8. { 9. Console.WriteLine("virtual method defined in the base class"); 10. } 11. } 12. 13. class myDerived : myBase 14. { 15. // hiding the implementation of base class method 16. public new void VirtualMethod() 17. { 18. Console.WriteLine("virtual method defined in the Derive class"); 19. 20. //still access the base class method 21. base.VirtualMethod(); 22. } 80 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. } class virtualClass { static void Main(string[] args) { // class instance new myDerived().VirtualMethod(); Console.ReadKey(); } } 33. } Abstraction Abstraction is "To represent the essential feature without representing the background details." Abstraction lets you focus on what the object does instead of how it does it. Abstraction provides you a generalized view of your classes or objects by providing relevant information. It is the process of hiding the working style of an object and showing the information of an object in an understandable manner. Real-world Example of Abstraction Suppose you have an object Mobile Phone. Suppose you have 3 mobile phones as in the following: Nokia 1400 (Features: Calling, SMS) Nokia 2700 (Features: Calling, SMS, FM Radio, MP3, Camera) Black Berry (Features:Calling, SMS, FM Radio, MP3, Camera, Video Recording, Reading Emails) Abstract information (necessary and common information) for the object "Mobile Phone" is that it makes a call to any number and can send SMS. So that, for a mobile phone object you will have the abstract class as in the following, 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. abstract class MobilePhone { public void Calling(); public void SendSMS(); } public class Nokia1400: MobilePhone {} public class Nokia2700: MobilePhone { public void FMRadio(); public void MP3(); public void Camera(); } public class BlackBerry: MobilePhone { 81 12. 13. 14. 15. 16. 17. public void FMRadio(); public void MP3(); public void Camera(); public void Recording(); public void ReadAndSendEmails(); } Abstraction means putting all the variables and methods in a class that are necessary. For example: Abstract class and abstract method. Abstraction is a common thing. Example If somebody in your college tells you to fill in an application form, you will provide your details, like name, address, date of birth, which semester, percentage you have etcetera. If some doctor gives you an application to fill in the details, you will provide the details, like name, address, date of birth, blood group, height and weight. See in the preceding example what is in common? Age, name and address, so you can create a class that consists of the common data. That is called an abstract class. That class is not complete and it can be inherited by other classes. Abstract Classes C# allows both classes and functions to be declared abstract using the abstract keyword. You can't create an instance of an abstract class. An abstract member has a signature but no function body and they must be overridden in any non-abstract derived class. Abstract classes exist primarily for inheritance. Member functions, properties and indexers can be abstract. A class with one or more abstract members must be abstract as well. Static members can't be abstract. In this example, we are declaring an abstract class Employess with a method displayData() that does not have an implementation. Then we are implementing the displayData() body in the derived class. One point to be noted here is that we have to prefixe the abstract method with the override keyword in the derived class. 1. using System; 2. namespace oops 3. { 4. //abstract class 82 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. } public abstract class Employess { //abstract method with no implementation public abstract void displayData(); } //derived class public class test : Employess { //abstract class method implementation public override void displayData() { Console.WriteLine("Abstract class method"); } } class abstractClass { static void Main(string[] args) { // class instance new test().displayData(); } } Sealed Classes Sealed classes are the reverse of abstract classes. While abstract classes are inherited and are refined in the derived class, sealed classes cannot be inherited. You can create an instance of a sealed class. A sealed class is used to prevent further refinement through inheritance. Suppose you are a developer of a class library and some of the classes in the class library are extensible but other classes are not extensible so in that case those classes are marked as sealed. 1. using System; 2. namespace oops 3. { 4. sealed class SealedClass 5. { 6. void myfunv(); 7. } 8. 9. public class test : SealedClass //wrong. will give compilation error 10. { 11. } 12. } 83 Interface An interface is a set of related functions that must be implemented in a derived class. Members of an interface are implicitly public and abstract. Interfaces are similar to abstract classes. First, both types must be inherited; second, you cannot create an instance of either. Although there are several differences as in the following; • • • • An Abstract class can contain some implementations but an interface can't. An Interface can only inherit other interfaces but abstract classes can inherit from other classes and interfaces. An Abstract class can contain constructors and destructors but an interface can't. An Abstract class contains fields but interfaces don't. So the question is, which of these to choose? Select interfaces because with an interface, the derived type still can inherit from another type and interfaces are more straightforward than abstract classes. 1. using System; 2. namespace oops 3. { 4. // interface 5. public interface xyz 6. { 7. void methodA(); 8. void methodB(); 9. } 10. 11. // interface method implementation 12. class test : xyz 13. { 14. public void methodA() 15. { 16. Console.WriteLine("methodA"); 17. } 18. public void methodB() 19. { 20. Console.WriteLine("methodB"); 21. } 22. } 23. class interfaceDemo 24. { 25. static void Main(string[] args) 26. { 27. test obj = new test(); 28. obj.methodA(); 29. obj.methodB(); 30. } 31. } 84 32. } An interface can be inherited from other interfaces as in the following: 1. public interface xyz 2. { 3. void methodA(); 4. void methodB(); 5. } 6. 7. public interface abc : xyz 8. { 9. void methodC(); 10. } Polymorphism Polymorphism is a Greek word, meaning "one name many forms". In other words, one object has many forms or has one name with multiple functionalities. "Poly" means many and "morph" means forms. Polymorphism provides the ability to a class to have multiple implementations with the same name. It is one of the core principles of Object Oriented Programming after encapsulation and inheritance. In this article, you'll learn what polymorphism is, how it works, and how to implement polymorphism in C#. Types of Polymorphism There are two types of polymorphism in C#: • • Static / Compile Time Polymorphism. Dynamic / Runtime Polymorphism. 85 Static or Compile Time Polymorphism It is also known as Early Binding. Method overloading is an example of Static Polymorphism. In overloading, the method / function has a same name but different signatures. It is also known as Compile Time Polymorphism because the decision of which method is to be called is made at compile time. Overloading is the concept in which method names are the same with a different set of parameters. Here C# compiler checks the number of parameters passed and the type of parameter and make the decision of which method to call and it throw an error if no matching method is found. In the following example, a class has two methods with the same name "Add" but with different input parameters (the first method has three parameters and the second method has two parameters). 1. public class TestData 2. { 3. public int Add(int a, int b, int c) 4. { 5. return a + b + c; 6. } 7. public int Add(int a, int b) 8. { 9. return a + b; 10. } 11. } 12. class Program 13. { 14. static void Main(string[] args) 15. { 16. TestData dataClass = new TestData(); 17. int add2 = dataClass.Add(45, 34, 67); 18. int add1 = dataClass.Add(23, 34); 86 19. } 20. } Dynamic / Runtime Polymorphism Dynamic / runtime polymorphism is also known as late binding. Here, the method name and the method signature (number of parameters and parameter type must be the same and may have a different implementation). Method overriding is an example of dynamic polymorphism. Method overriding can be done using inheritance. With method overriding it is possible for the base class and derived class to have the same method name and same something. The compiler would not be aware of the method available for overriding the functionality, so the compiler does not throw an error at compile time. The compiler will decide which method to call at runtime and if no method is found then it throws an error. 1. public class Drawing 2. { 3. public virtual double Area() 4. { 5. return 0; 6. } 7. } 8. 9. public class Circle : Drawing 10. { 11. public double Radius { get; set; } 12. public Circle() 13. { 14. Radius = 5; 15. } 16. public override double Area() 17. { 18. return (3.14) * Math.Pow(Radius, 2); 19. } 20. } 21. 87 22. public class Square : Drawing 23. { 24. public double Length { get; set; } 25. public Square() 26. { 27. Length = 6; 28. } 29. public override double Area() 30. { 31. return Math.Pow(Length, 2); 32. } 33. } 34. 35. public class Rectangle : Drawing 36. { 37. public double Height { get; set; } 38. public double Width { get; set; } 39. public Rectangle() 40. { 41. Height = 5.3; 42. Width = 3.4; 43. } 44. public override double Area() 45. { 46. return Height * Width; 47. } 48. } 49. 50. class Program 51. { 52. static void Main(string[] args) 53. { 54. 55. Drawing circle = new Circle(); 56. Console.WriteLine("Area :" + circle.Area()); 57. 58. Drawing square = new Square(); 59. Console.WriteLine("Area :" + square.Area()); 60. 61. Drawing rectangle = new Rectangle(); 62. Console.WriteLine("Area :" + rectangle.Area()); 63. } 64. } 88 The compiler requires an Area() method and it compiles successfully but the right version of the Area() method is not being determined at compile time but determined at runtime. Finally the overriding methods must have the same name and signature (number of parameters and type), as the virtual or abstract method defined in the base class method and that it is overriding in the derived class. A method or function of the base class is available to the child (derived) class without the use of the "overriding" keyword. The compiler hides the function or method of the base class. This concept is known as shadowing or method hiding. You may find the difference between overriding and shadowing here. Preventing Derived class from overriding virtual members Virtual members remain “virtual” indefinitely. In other words, virtual members remain “virtual” regardless of how many classes have been between virtual members and the class that originally declared it. For example, if class X has the virtual method "A" and the class Y is derived from X and the class Z is derived from Y, class Z inherits the virtual method "A" and override it. 89 1. public class X 2. { 3. public virtual void A() 4. { 5. } 6. } 7. public class Y : X 8. { 9. public override void A() 10. { 11. } 12. } A derived class is able to stop virtual inheritance by declaring an override member as "sealed". 1. public class Y : X 2. { 3. public sealed override void A() 4. { 5. } 6. } Accessing Base class virtual member Using the "base" keyword, the derived class is able to access the method. 1. public class X 2. { 3. public virtual void A() 4. { 5. } 6. } 7. public class Y : X 8. { 9. public override void A() 10. { 11. base.A(); 12. } 13. } 90 Course Materials: https://www.c-sharpcorner.com/UploadFile/84c85b/object-oriented-programming-using-CSharpnet/#:~:text=C%23%20is%20an%20object%20oriented,%2C%20data%20hiding%2C%20and% 20inheritance.&text=They%20are%20encapsulation%2C%20inheritance%2C%20polymorphism ,brief%20look%20at%20these%20concepts. https://www.c-sharpcorner.com/UploadFile/mkagrahari/introduction-to-object-orientedprogramming-concepts-in-C-Sharp/ https://www.c-sharpcorner.com/UploadFile/2072a9/method-overriding-in-C-Sharp/ https://www.c-sharpcorner.com/article/encapsulation-in-C-Sharp/ https://www.c-sharpcorner.com/UploadFile/ff2f08/understanding-polymorphism-in-C-Sharp/ Activities/Assessments: A. This post-test is intended to gauge what you already know about the Language Basics and Object-Oriented Programming Concepts of C#. Please answer the following questions by encircling the letter of the correct answer. 1. What will be the output of the following code snippet? using System; public class emp { public static int age = 40; public static int salary = 25000; } public class record :emp { new public static int salary = 50000; static void Main(string[] args) { Console.WriteLine(emp.age + " " + emp.salary + " } } " + salary); a. 40, 25000, 50000 b. 40, 25000, 25000 c. 40, 50000, 50000 d. Error 2. Which of the following keyword, enables to modify the data and behavior of a base class by replacing its member with a new derived member? a) overloads b) overrides c) new d) base 3. What will be the correct order of execution of function func1(), func2() & func3() in the given code snippet? class baseclass { public void func1() {} public virtual void func2() {} public virtual void func3() {} 91 } class derivedclass :baseclass { new public void func1() {} public override void func2() {} public new void func3() {} } class Program { static void Main(string[] args) { baseclass b = new derivedclass(); b.func1 (); b.func2 (); b.func3 (); } } a) func1() of derived class get executed func2() of derived class get executed func3() of base class get executed b) func1() of base class get executed func2() of derived class get executed func3() of derived class get executed c) func1() of derived class get executed func2() of base class get executed func3() of base class get executed d) func1() of base class get executed func2() of derived class get executed func3() of base class get executed 4. Which of the following keywords is used to refer base class constructor to subclass constructor? a) this b) static c) base d) extend 5. What will be the output of the following code snippet? using System; class sample { int i; public sample(int x) { i = x; Console.WriteLine("Tech"); } } class derived : sample { public derived(int x) :base(x) { Console.WriteLine("Beamers"); } } class Program 92 { static void Main(string[] args) { derived k = new derived(12); Console.ReadLine(); } } a) TechBeamers b) 12 Tech c) Beamers 12 d) Compile time error 6. What will be the output of the following code snippet? using System; class sample { int i; public sample(int num) { num = 12; int j = 12; int val = num * j; Console.WriteLine(val); } } class sample1 : sample { public sample1(int a) :base(a) { a = 13; int b = 13; Console.WriteLine(a + b); } } class sample2 : sample1 { public sample2(int k) :base(k) { k = 24; int o = 6 ; Console.WriteLine(k /o); } } class Program { public static void Main(string[] args) { sample2 t = new sample2(10); Console.ReadLine(); } } a) 4, 26, 144 b) 26, 4, 144 c) 144, 26, 4 d) 0, 0, 0 93 7. Which of the following options represents the type of class which does not have its own objects but acts as a base class for its subclass? a) Static class b) Sealed class c) Abstract class d) Derived class 8. What will be the output of the following code snippet? using System; namespace TechBeamers { abstract class baseclass { public int i; public abstract void print(); } class derived: baseclass { public int j; public int val; public override void print() { val = i + j; Console.WriteLine(+i + "\n" + +j); Console.WriteLine("sum is:" +val); } } class Program { static void Main(string[] args) { baseclass obj = new derived(); obj.i = 2; derived obj1 = new derived(); obj1.j = 10; obj.print(); Console.ReadLine(); } } } a) 2 10 Sum is: 12 b) 0 10 Sum is: 10 c) 2 0 Sum is: 2 d) 0 0 Sum is: 0 9. Which of the following represents a class that inherits an abstract class but it does not define all of its functions? a) Abstract b) A simple class c) Static class d) derived class 94 10. What will be the output of the following code snippet? using System; namespace TechBeamers { public abstract class sample { public int i = 7; public abstract void print(); } class sample1: sample { public int j; public override void print() { Console.WriteLine(i); Console.WriteLine(j); } } class Program { static void Main(string[] args) { sample1 obj = new sample1(); sample obj1 = new sample1(); obj.j = 1; obj1.i = 8; obj.print(); Console.ReadLine(); } } } a) 0, 8 b) 1, 8 c) 1, 7 d) 7, 1 B. Application Create a C# program that represents the following UML class diagram. The diagram represents public, private, and protected attributes as well as class dependency and inheritance. 95 Module 4 Overview: WPF stands for Windows Presentation Foundation. It is a powerful framework for building Windows applications. This module explains the features that you need to understand to build WPF applications and how it brings a fundamental change in Windows applications. Module Objectives: After successful Completion of this module, you should be able to: • • • Implement GUI that facilitates a customizable look and feel Develop applications using key foundation services Develop graphic and GUI components using WPF 96 What is WPF? WPF, which stands for Windows Presentation Foundation, is Microsoft's latest approach to a GUI framework, used with the .NET framework. But what IS a GUI framework? GUI stands for Graphical User Interface, and you are probably looking at one right now. Windows has a GUI for working with your computer, and the browser that you are likely reading this document in has a GUI that allows you to surf the web. A GUI framework allows you to create an application with a wide range of GUI elements, like labels, textboxes, and other well-known elements. Without a GUI framework you would have to draw these elements manually and handle all the user interaction scenarios like text and mouse input. This is a LOT of work, so instead, most developers will use a GUI framework which will do all the basic work and allow the developers to focus on making great applications. There are a lot of GUI frameworks out there, but for .NET developers, the most interesting ones are currently WinForms and WPF. WPF is the newest, but Microsoft is still maintaining and supporting WinForms. WPF is a combination of XAML (markup) and C#/VB.NET/any other .NET language. All of it can be edited in any text editor, even Notepad included in Windows, and then compiled from the command line. However, most developers prefer to use an IDE (Integrated Development Environment), since it makes everything, from writing code to designing the interface and compiling it all so much easier. The preferred choice for a .NET/WPF IDE is Visual Studio, which costs quite a bit of money though. Luckily, Microsoft has decided to make it easy and free for everyone to get started with .NET and WPF, so they have created a free version of Visual Studio, called Visual Studio Community. This version contains slightly less functionality than the real Visual Studio, but it has everything that you need to get started learning WPF and make real applications. WPF Architecture Before WPF, the other user interface frameworks offered by Microsoft such as MFC and Windows forms, were just wrappers around User32 and GDI32 DLLs, but WPF makes only minimal use of User32. So, • WPF is more than just a wrapper. • It is a part of the .NET framework. • It contains a mixture of managed and unmanaged code. The major components of WPF architecture are as shown in the figure below. The most important code part of WPF are • Presentation Framework • Presentation Core • Milcore 97 The presentation framework and the presentation core have been written in managed code. Milcore is a part of unmanaged code which allows tight integration with DirectX (responsible for display and rendering). CLR makes the development process more productive by offering many features such as memory management, error handling, etc. Advantages In the earlier GUI frameworks, there was no real separation between how an application looks like and how it behaved. Both GUI and behavior were created in the same language, e.g., C# or VB.Net which would require more effort from the developer to implement both UI and behavior associated with it. In WPF, UI elements are designed in XAML while behaviors can be implemented in procedural languages such C# and VB.Net. So, it very easy to separate behavior from the designer code. With XAML, the programmers can work in parallel with the designers. The separation between a GUI and its behavior can allow us to easily change the look of a control by using styles and templates. Features WPF is a powerful framework to create Windows application. It supports many great features, some of which have been listed below − Feature Description Control inside a Control Allows to define a control inside another control as a content. Data binding Mechanism to display and interact with data between UI elements and data object on user interface. Media services Provides an integrated system for building user interfaces with common media elements like images, audio, and video. Templates In WPF you can define the look of an element directly with a Template Animations Building interactivity and movement on user Interface Alternative input Supports multi-touch input on Windows 7 and above. Direct3D Allows to display more complex graphics and custom themes 98 Create a Simple Application When you create an application in Visual Studio, you first create a project and a solution. For this example, you'll create a Windows Presentation Foundation (WPF) project. 1. Open Visual Studio 2019. 2. On the start window, choose Create new project. 3. On the Create a new project screen, search for "WPF," choose WPF App (.NET Core), and then choose Next. 99 4. At the next screen, give the project a name, HelloWPFApp, and choose Create. Visual Studio creates the HelloWPFApp project and solution, and Solution Explorer shows the various files. The WPF Designer shows a design view and a XAML view of MainWindow.xaml in a split view. You can slide the splitter to show more or less of either view. You can choose to see only the visual view or only the XAML view. After you create the project, you can customize it. To do so, choose Properties Window from the View menu, or press F4. Then, you can display and change options for project items, controls, and other items in an application. 100 Change the name of MainWindow.xaml Let's give MainWindow a more specific name. In Solution Explorer, on MainWindow.xaml and choose Rename. Rename the file to Greetings.xaml. right-click Design the user interface (UI) If the designer is not open, select Greetings.xaml and press Shift+F7 to open the designer. We'll add three types of controls to this application: a TextBlock control, two RadioButton controls, and a Button control. Add a TextBlock control 1. Press Ctrl+Q to activate the search box and type Toolbox. Choose View > Toolbox from the results list. 2. In the Toolbox, expand the Common WPF Controls node to see the TextBlock control. 3. Add a TextBlock control to the design surface by choosing the TextBlock item and dragging it to the window on the design surface. Center the control near the top of the window. In Visual Studio 2019 and later, you can use the red guidelines to center the control. Your window should resemble the following illustration: 101 The XAML markup should look something like the following example: <Grid> <TextBlock HorizontalAlignment="Left" Margin="387,60,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/> </Grid> Customize the text in the text block 1. In the XAML view, locate the markup for TextBlock and change the Text attribute from TextBox to Select a message option and then choose the Display button. The XAML markup should look something like the following example: <Grid> <TextBlock HorizontalAlignment="Left" Margin="387,60,0,0" TextWrapping="Wrap" Text="Select a message option and then choose the Display button." VerticalAlignment="Top"/> </Grid> 2. Center the TextBlock again if you like, and then save your changes by pressing Ctrl+S or using the File menu item. Next, you'll add two RadioButton controls to the form. Add radio buttons 1. In the Toolbox, find the RadioButton control. 102 2. Add two RadioButton controls to the design surface by choosing the RadioButton item and dragging it to the window on the design surface. Move the buttons (by selecting them and using the arrow keys) so that the buttons appear side by side under the TextBlock control. Use the red guidelines to align the controls. Your window should look like this: 3. In the Properties window for the the Name property (the property at to HelloButton. 103 left the RadioButton control, change top of the Properties window) 4. In the Properties window for the right RadioButton control, the Name property to GoodbyeButton, and then save your changes. change Next, you'll add display text for each RadioButton control. The following procedure updates the Content property for a RadioButton control. Add display text for each radio button 1. Update the Content attribute for the HelloButton and GoodbyeButton to "Hello" and "Goodbye" in the XAML. The XAML markup should now look similar to the following example: <Grid> <TextBlock HorizontalAlignment="Left" Margin="252,47,0,0" TextWrapping="Wrap" Text="Select a message option and then choose the Display button." VerticalAlignment="Top"/> <RadioButton x:Name="HelloButton" Content="Hello" HorizontalAlignment="Left" Margin="297,161,0,0" VerticalAlignment="Top"/> <RadioButton x:Name="GoodbyeButton" Content="Goodbye" HorizontalAlignment="Left" Margin="488,161,0,0" VerticalAlignment="Top"/> </Grid> Set a radio button to be checked by default In this step, we'll set HelloButton to be checked by default so that one of the two radio buttons is always selected. 1. In the XAML view, locate the markup for HelloButton. 2. Add an IsChecked attribute and set it to True. Specifically, add IsChecked="True". 104 The XAML markup should now look similar to the following example: <Grid> <TextBlock HorizontalAlignment="Left" Margin="252,47,0,0" TextWrapping="Wrap" Text="Select a message option and then choose the Display button." VerticalAlignment="Top"/> <RadioButton x:Name="HelloButton" Content="Hello" IsChecked="True" HorizontalAlignment="Left" Margin="297,161,0,0" VerticalAlignment="Top"/> <RadioButton x:Name="GoodbyeButton" Content="Goodbye" HorizontalAlignment="Left" Margin="488,161,0,0" VerticalAlignment="Top"/> </Grid> The final UI element that you'll add is a Button control. Add the button control 1. In the Toolbox, find the Button control, and then add it to the design surface under the RadioButton controls by dragging it to the form in the design view. If you're using Visual Studio 2019 or later, a red line helps you center the control. 2. In the XAML view, change the value of Content for the Button control from Content="Button" to Content="Display", and then save the changes. Your window should resemble the following illustration. The XAML markup should now look similar to the following example: <Grid> <TextBlock HorizontalAlignment="Left" Margin="252,47,0,0" TextWrapping="Wrap" Text="Select a message option and then choose the Display button." VerticalAlignment="Top"/> <RadioButton x:Name="HelloButton" Content="Hello" Margin="297,161,0,0" VerticalAlignment="Top"/> 105 IsChecked="True" HorizontalAlignment="Left" <RadioButton x:Name="GoodbyeButton" Content="Goodbye" HorizontalAlignment="Left" Margin="488,161,0,0" VerticalAlignment="Top"/> <Button Content="Display" HorizontalAlignment="Left" Margin="377,270,0,0" VerticalAlignment="Top" Width="75"/> </Grid> Add code to the display button When this application runs, a message box appears after a user chooses a radio button and then chooses the Display button. One message box will appear for Hello, and another will appear for Goodbye. To create this behavior, you'll add code to the Button_Click event in Greetings.xaml.cs. 1. On the design surface, double-click the Display button. Greetings.xaml.cs opens, with the cursor in the Button_Click event. private void Button_Click(object sender, RoutedEventArgs e) { } 2. Enter the following code: if (HelloButton.IsChecked == true) { MessageBox.Show("Hello."); } else if (GoodbyeButton.IsChecked == true) { MessageBox.Show("Goodbye."); } 3. Save the application. Debug and test the application Find and fix errors In this step, you'll find the error that we caused earlier by changing the name of the MainWindow.xaml file. Start debugging and find the error 1. Start the debugger by pressing F5 or selecting Debug, then Start Debugging. A Break Mode window appears, and the Output window indicates that an IOException has occurred: Cannot locate resource 'mainwindow.xaml'. 106 2. Stop the debugger by choosing Debug > Stop Debugging. We renamed MainWindow.xaml to Greetings.xaml at the start of this tutorial, but the code still refers to MainWindow.xaml as the startup URI for the application, so the project can't start. Specify Greetings.xaml as the startup URI 1. In Solution Explorer, open the App.xaml file. 2. Change StartupUri="MainWindow.xaml" to StartupUri="Greetings.xaml", and then save the changes. Start the debugger again (press F5). You should see the Greetings window of the application. Now close the application window to stop debugging. What is XAML? XAML, which stands for eXtensible Application Markup Language, is Microsoft's variant of XML for describing a GUI. In previous GUI frameworks, like WinForms, a GUI was created in the same language that you would use for interacting with the GUI, e.g. C# or VB.NET and usually maintained by the designer (e.g. Visual Studio), but with XAML, Microsoft is going another way. Much like with HTML, you are able to easily write and edit your GUI. 107 This is not really a XAML tutorial, but I will briefly tell you about how you use it, because it's such an essential part of WPF. Whether you're creating a Window or a Page, it will consist of a XAML document and a CodeBehind file, which together creates the Window/Page. The XAML file describes the interface with all its elements, while the CodeBehind handles all the events and has access to manipulate with the XAML controls. Basic XAML Creating a control in XAML is as easy as writing its name, surrounded by angle brackets. For instance, a Button looks like this: <Button> XAML tags has to be ended, either by writing the end tag or by putting a forward slash at the end of the start tag: <Button></Button> Or <Button /> A lot of controls allow you to put content between the start and end tags, which is then the content of the control. For instance, the Button control allows you to specify the text shown on it between the start and end tags: <Button>A button</Button> HTML is not case-sensitive, but XAML is, because the control name has to correspond to a type in the .NET framework. The same goes for attribute names, which corresponds to the properties of the control. Here's a button where we define a couple of properties by adding attributes to the tag: <Button FontWeight="Bold" Content="A button" /> We set the FontWeight property, giving us bold text, and then we set the Content property, which is the same as writing the text between the start and end tag. However, all attributes of a control may also be defined like this, where they appear as child tags of the main control, using the Control-Dot-Property notation: <Button> <Button.FontWeight>Bold</Button.FontWeight> <Button.Content>A button</Button.Content> </Button> The result is exactly the same as above, so in this case, it's all about syntax and nothing else. However, a lot of controls allow content other than text, for instance other controls. Here's an 108 example where we have text in different colors on the same button by using several TextBlock controls inside of the Button: <Button> <Button.FontWeight>Bold</Button.FontWeight> <Button.Content> <WrapPanel> <TextBlock Foreground="Blue">Multi</TextBlock> <TextBlock Foreground="Red">Color</TextBlock> <TextBlock>Button</TextBlock> </WrapPanel> </Button.Content> </Button> The Content property only allows for a single child element, so we use a WrapPanel to contain the differently colored blocks of text. Panels, like the WrapPanel, plays an important role in WPF and we will discuss them in much more details later on - for now, just consider them as containers for other controls. The exact same result can be accomplished with the following markup, which is simply another way of writing the same: <Button FontWeight="Bold"> <WrapPanel> <TextBlock Foreground="Blue">Multi</TextBlock> <TextBlock Foreground="Red">Color</TextBlock> <TextBlock>Button</TextBlock> </WrapPanel> </Button> Events in XAML Most modern UI frameworks are event driven and so is WPF. All of the controls, including the Window (which also inherits the Control class) exposes a range of events that you may subscribe to. You can subscribe to these events, which means that your application will be notified when they occur and you may react to that. There are many types of events, but some of the most commonly used are there to respond to the user's interaction with your application using the mouse or the keyboard. On most controls you will find events like KeyDown, KeyUp, MouseDown, MouseEnter, MouseLeave, MouseUp and several others. We will look more closely at how events work in WPF, since this is a complex topic, but for now, you need to know how to link a control event in XAML to a piece of code in your Code-behind file. Have a look at this example: <Window x:Class="WpfTutorialSamples.XAML.EventsSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 109 Title="EventsSample" Height="300" Width="300"> <Grid Name="pnlMainGrid" MouseUp="pnlMainGrid_MouseUp" Background="LightBlue"> </Grid> </Window> Notice how we have subscribed to the MouseUp event of the Grid by writing a method name. This method needs to be defined in code-behind, using the correct event signature. In this case it should look like this: private void pnlMainGrid_MouseUp(object sender, MouseButtonEventArgs e) { MessageBox.Show("You clicked me at " + e.GetPosition(this).ToString()); } The MouseUp event uses a delegate called MouseButtonEventHandler, which you subscribe to. It has two parameters, a sender (the control which raised the event) and a MouseButtonEventArgs object that will contain useful information. We use it in the example to get the position of the mouse cursor and tell the user about it. Several events may use the same delegate type - for instance, both MouseUp and MouseDown uses the MouseButtonEventHandler delegate, while the MouseMove event uses the MouseEventHandler delegate. When defining the event handler method, you need to know which delegate it uses and if you don't know that, you can look it up in the documentation. Fortunately, Visual Studio can help us to generate a correct event handler for an event. The easiest way to do this is to simply write the name of the event in XAML and then let the IntelliSense of VS do the rest for you: When you select <New Event Handler> Visual Studio will generate an appropriate event handler in your Code-behind file. It will be named <control name>_<event name>, in our case pnlMainGrid_MouseDown. Right-click in the event name and select Navigate to Event Handler and VS will take you right to it. 110 Subscribing to an event from Code-behind The most common way to subscribe to events is explained above, but there may be times where you want to subscribe to the event directly from Code-behind instead. This is done using the += C# syntax, where you add an event handler to event directly on the object. The full explanation of this belongs in a dedicated C# example, but for comparison, here's an example: using System; using System.Windows; using System.Windows.Input; namespace WpfTutorialSamples.XAML { public partial class EventsSample : Window { public EventsSample() { InitializeComponent(); pnlMainGrid.MouseUp += new MouseButtonEventHandler(pnlMainGrid_MouseUp); } private void pnlMainGrid_MouseUp(object sender, MouseButtonEventArgs e) { MessageBox.Show("You clicked me at " + e.GetPosition(this).ToString()); } } } Once again, you need to know which delegate to use, and once again, Visual Studio can help you with this. As soon as you write: pnlMainGrid.MouseDown += Visual Studio will offer its assistance: Simply press the [Tab] key twice to have Visual Studio generate the correct event handler for you, right below the current method, ready for implementation. When you subscribe to the events like this, you don't need to do it in XAML. 111 Basic Controls The TextBlock control TextBlock is not a control, per se, since it doesn't inherit from the Control class, but it's used much like any other control in the WPF framework, so we'll call it a control to keep things simple. The TextBlock control is one of the most fundamental controls in WPF, yet it's very useful. It allows you to put text on the screen, much like a Label control does, but in a simpler and less resource demanding way. A common understanding is that a Label is for short, one-line texts (but may include e.g. an image), while the TextBlock works very well for multiline strings as well, but can only contain text (strings). Both the Label and the TextBlock offers their own unique advantages, so what you should use very much depends on the situation. We already used a TextBlock control in the "Hello, WPF!" article, but for now, let's have a look at the TextBlock in its simplest form: <Window x:Class="WpfTutorialSamples.Basic_controls.TextBlockSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TextBlockSample" Height="100" Width="200"> <Grid> <TextBlock>This is a TextBlock</TextBlock> </Grid> </Window> That's as simple as it comes and if you have read the previous chapters of this tutorial, then there should be nothing new here. The text between the TextBlock is simply a shortcut for setting the Text property of the TextBlock. For the next example, let's try a longer text to show how the TextBlock deals with that. I've also added a bit of margin, to make it look just a bit better: <Window x:Class="WpfTutorialSamples.Basic_controls.TextBlockSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TextBlockSample" Height="100" Width="200"> <Grid> <TextBlock Margin="10">This is a TextBlock control and it comes with a very long text</TextBlock> </Grid> </Window> 112 Dealing with long strings As you will soon realize from the screenshot, the TextBlock is perfectly capable of dealing with long, multiline texts, but it will not do anything by default. In this case the text is too long to be rendered inside the window, so WPF renders as much of the text as possible and then just stops. Fortunately, there are several ways of dealing with this. In the next example I'll show you all of them, and then I'll explain each of them afterwards: <Window x:Class="WpfTutorialSamples.Basic_controls.TextBlockSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TextBlockSample" Height="200" Width="250"> <StackPanel> <TextBlock Margin="10" Foreground="Red"> This is a TextBlock control<LineBreak /> with multiple lines of text. </TextBlock> <TextBlock Margin="10" TextTrimming="CharacterEllipsis" Foreground="Green"> This is a TextBlock control with text that may not be rendered completely, which will be indicated with an ellipsis. </TextBlock> <TextBlock Margin="10" TextWrapping="Wrap" Foreground="Blue"> This is a TextBlock control with automatically wrapped text, using the TextWrapping property. </TextBlock> </StackPanel> </Window> 113 So, we have three TextBlock controls, each with a different color (using the Foreground property) for an easier overview. They all handle the fact that their text content is too long in different ways: The red TextBlock uses a LineBreak tag to manually break the line at a designated location. This gives you absolute control over where you want the text to break onto a new line, but it's not very flexible for most situations. If the user makes the window bigger, the text will still wrap at the same position, even though there may now be room enough to fit the entire text onto one line. The green TextBlock uses the TextTrimming property with the value CharacterEllipsis to make the TextBlock show an ellipsis (...) when it can't fit any more text into the control. This is a common way of showing that there's more text, but not enough room to show it. This is great when you have text that might be too long but you absolutely don't want it to use more than one line. As an alternative to CharacterEllipsis you may use WordEllipsis, which will trim the text at the end of the last possible word instead of the last possible character, preventing that a word is only shown in part. The blue TextBlock uses the TextWrapping property with the value Wrap, to make the TextBlock wrap to the next line whenever it can't fit anymore text into the previous line. Contrary to the first TextBlock, where we manually define where to wrap the text, this happens completely automatic and even better: It's also automatically adjusted as soon as the TextBlock get more or less space available. Try making the window in the example bigger or smaller and you will see how the wrapping is updated to match the situation. This was all about dealing with simple strings in the TextBlock. In the next chapter, we'll look into some of the more advanced functionality of the TextBlock, which allows us to create text of various styles within the TextBlock and much more. The Label control The Label control, in its most simple form, will look very much like the TextBlock which we used in another article. You will quickly notice though that instead of a Text property, the Label has a Content property. The reason for that is that the Label can host any kind of control directly inside of it, instead of just text. This content can be a string as well though, as you will see in this first and very basic example: <Window x:Class="WpfTutorialSamples.Basic_controls.LabelControlSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="LabelControlSample" Height="100" Width="200"> <Grid> <Label Content="This is a Label control." /> </Grid> </Window> 114 Another thing you might notice is the fact that the Label, by default, has a bit of padding, allowing the text to be rendered a few pixels away from the top, left corner. This is not the case for the TextBlock control, where you will have to specify it manually. In a simple case like this, where the content is simply a string, the Label will actually create a TextBlock internally and show your string in that. The Label control vs. the TextBlock control So why use a Label at all then? Well, there are a few important differences between the Label and the TextBlock. The TextBlock only allows you to render a text string, while the Label also allows you to: ▪ ▪ ▪ ▪ Specify a border Render other controls, e.g. an image Use templated content through the ContentTemplate property Use access keys to give focus to related controls The last bullet point is actually one of the main reasons for using a Label over the TextBlock control. Whenever you just want to render simple text, you should use the TextBlock control, since it's lighter and performs better than the Label in most cases. Label and Access keys (mnemonics) In Windows and other operating systems as well, it's common practice that you can access controls in a dialog by holding down the [Alt] key and then pressing a character which corresponds to the control that you wish to access. The character to press will be highlighted when you hold down the [Alt] key. TextBlock controls doesn't support this functionality, but the Label does, so for control labels, the Label control is usually an excellent choice. Let's look at an example of it in action: <Window x:Class="WpfTutorialSamples.Basic_controls.LabelControlSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="LabelControlSample" Height="180" Width="250"> <StackPanel Margin="10"> <Label Content="_Name:" Target="{Binding ElementName=txtName}" /> <TextBox Name="txtName" /> <Label Content="_Mail:" Target="{Binding ElementName=txtMail}" /> <TextBox Name="txtMail" /> </StackPanel> </Window> 115 The screenshot shows our sample dialog as it looks when the Alt key is pressed. Try running it, holding down the [Alt] key and then pressing N and M. You will see how focus is moved between the two textboxes. So, there's several new concepts here. First of all, we define the access key by placing an underscore (_) before the character. It doesn't have to be the first character, it can be before any of the characters in your label content. The common practice is to use the first character that's not already used as an access key for another control. We use the Target property to connect the Label and the designated control. We use a standard WPF binding for this, using the ElementName property, all of which we will describe later on in this tutorial. The binding is based on the name of the control, so if you change this name, you will also have to remember to change the binding. Using controls as Label content As already mentioned, the Label control allows you to host other controls, while still keeping the other benefits. Let's try an example where we have both an image and a piece of text inside the Label, while also having an access key for each of the labels: <Window x:Class="WpfTutorialSamples.Basic_controls.LabelControlAdvancedSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="LabelControlAdvancedSample" Height="180" Width="250"> <StackPanel Margin="10"> <Label Target="{Binding ElementName=txtName}"> <StackPanel Orientation="Horizontal"> <Image Source="http://cdn1.iconfinder.com/data/icons/fatcow/16/bullet_green.png" /> <AccessText Text="_Name:" /> </StackPanel> </Label> <TextBox Name="txtName" /> <Label Target="{Binding ElementName=txtMail}"> <StackPanel Orientation="Horizontal"> <Image Source="http://cdn1.iconfinder.com/data/icons/fatcow/16/bullet_blue.png" /> <AccessText Text="_Mail:" /> </StackPanel> </Label> 116 <TextBox Name="txtMail" /> </StackPanel> </Window> This is just an extended version of the previous example - instead of a simple text string, our Label will now host both an image and a piece of text (inside the AccessText control, which allows us to still use an access key for the label). Both controls are inside a horizontal StackPanel, since the Label, just like any other ContentControl derivate, can only host one direct child control. The TextBox control The TextBox control is the most basic text-input control found in WPF, allowing the end-user to write plain text, either on a single line, for dialog input, or in multiple lines, like an editor. Single-line TextBox The TextBox control is such a commonly used thing that you actually don't have to use any properties on it, to have a full-blown editable text field. Here's a barebone example: <Window x:Class="WpfTutorialSamples.Basic_controls.TextBoxSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TextBoxSample" Height="80" Width="250"> <StackPanel Margin="10"> <TextBox /> </StackPanel> </Window> 117 That's all you need to get a text field. I added the text after running the sample and before taking the screenshot, but you can do it through markup as well, to pre-fill the textbox, using the Text property: <TextBox Text="Hello, world!" /> Try right-clicking in the TextBox. You will get a menu of options, allowing you to use the TextBox with the Windows Clipboard. The default keyboard shortcuts for undoing and redoing (Ctrl+Z and Ctrl+Y) should also work, and all of this functionality you get for free! Multi-line TextBox If you run the above example, you will notice that the TextBox control by default is a single-line control. Nothing happens when you press Enter and if you add more text than what can fit on a single line, the control just scrolls. However, making the TextBox control into a multi-line editor is very simple: <Window x:Class="WpfTutorialSamples.Basic_controls.TextBoxSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TextBoxSample" Height="160" Width="280"> <Grid Margin="10"> <TextBox AcceptsReturn="True" TextWrapping="Wrap" /> </Grid> </Window> I have added two properties: The AcceptsReturn makes the TextBox into a multi-line control by allowing the use of the Enter/Return key to go to the next line, and the TextWrapping property, which will make the text wrap automatically when the end of a line is reached. Spellcheck with TextBox As an added bonus, the TextBox control actually comes with automatic spell checking for English and a couple of other languages (as of writing, English, French, German, and Spanish languages are supported). It works much like in Microsoft Word, where spelling errors are underlined and you can right-click it for suggested alternatives. Enabling spell checking is very easy: <Window x:Class="WpfTutorialSamples.Basic_controls.TextBoxSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 118 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TextBoxSample" Height="160" Width="280"> <Grid Margin="10"> <TextBox AcceptsReturn="True" TextWrapping="Wrap" SpellCheck.IsEnabled="True" Language="en-US" /> </Grid> </Window> We have used the previous, multi-line textbox example as the basis and then I have added two new properties: The attached property from the SpellCheck class called IsEnabled, which simply enables spell checking on the parent control, and the Language property, which instructs the spell checker which language to use. Working with TextBox selections Just like any other editable control in Windows, the TextBox allows for selection of text, e.g. to delete an entire word at once or to copy a piece of the text to the clipboard. The WPF TextBox has several properties for working with selected text, all of them which you can read or even modify. In the next example, we will be reading these properties: <Window x:Class="WpfTutorialSamples.Basic_controls.TextBoxSelectionSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TextBoxSelectionSample" Height="150" Width="300"> <DockPanel Margin="10"> <TextBox SelectionChanged="TextBox_SelectionChanged" DockPanel.Dock="Top" /> <TextBox Name="txtStatus" AcceptsReturn="True" TextWrapping="Wrap" IsReadOnly="True" /> </DockPanel> </Window> The example consists of two TextBox controls: One for editing and one for outputting the current selection status to. For this, we set the IsReadOnly property to true, to prevent editing of the status TextBox. We subscribe the SelectionChanged event on the first TextBox, which we handle in the Code-behind: using System; using System.Text; 119 using System.Windows; using System.Windows.Controls; namespace WpfTutorialSamples.Basic_controls { public partial class TextBoxSelectionSample : Window { public TextBoxSelectionSample() { InitializeComponent(); } private void TextBox_SelectionChanged(object sender, RoutedEventArgs e) { TextBox textBox = sender as TextBox; txtStatus.Text = "Selection starts at character #" + textBox.SelectionStart + Environment.NewLine; txtStatus.Text += "Selection is " + textBox.SelectionLength + " character(s) long" + Environment.NewLine; txtStatus.Text += "Selected text: '" + textBox.SelectedText + "'"; } } } We use three interesting properties to accomplish this: SelectionStart , which gives us the current cursor position or if there's a selection: Where it starts. SelectionLength , which gives us the length of the current selection, if any. Otherwise it will just return 0. SelectedText , which gives us the currently selected string if there's a selection. Otherwise an empty string is returned. Modifying the selection All of these properties are both readable and writable, which means that you can modify them as well. For instance, you can set the SelectionStart and SelectionLength properties to select a custom range of text, or you can use the SelectedText property to insert and select a string. Just 120 remember that the TextBox has to have focus, e.g. by calling the Focus() method first, for this to work. The Button control No GUI framework would be complete without a Button control, so of course WPF has a nice one included, and just like the rest of the framework controls, it's very flexible and will allow you to accomplish almost anything. But let's start out with some basic examples. A Simple Button Just like many other WPF controls, a Button can be displayed simply by adding a Button tag to your Window. If you put text between the tags (or another control), it will act as the content of the Button: <Button>Hello, world!</Button> Pretty simple, right? Of course, the Button doesn't actually do anything yet, but if you point to it, you will find that it comes with a nice hover effect right out of the box. But let's make the Button do something, by subscribing to its Click event (more information about this process can be found in the article on subscribing to events in XAML): <Button Click="HelloWorldButton_Click">Hello, World!</Button> In Code-behind, you will need a matching method to handle the click: private void HelloWorldButton_Click(object sender, RoutedEventArgs e) { MessageBox.Show("Hello, world!"); } You now have a very basic button and when you click on it, a message will be displayed! 121 Formatted content Internally, simple text inside the Content of the Button is turned into a TextBlock control, which also means that you can control the same aspects of the text formatting. You will find several properties on the Button control for doing this, including (but not limited to) Foreground, Background, FontWeight and so on. In other words, it's very easy to change the formatting of the text inside a Button control: <Button Background="Beige" Foreground="Blue" FontWeight="Bold">Formatted Button</Button> By setting these properties directly on the Button, you are of course limited to applying the same formatting for all of the content, but if that's not good enough, just read on for even more advanced content formatting. Buttons with Advanced Content We have already talked about this several times, but one of the very cool things about WPF is the ability to replace simple text inside a control with other WPF controls. This also means that you don't have to limit your buttons to simple text, formatted in the same way - you can just add several text controls with different formatting. The WPF Button only supports one direct child control, but you can just make that a Panel, which will then host as many controls as you need to. You can use this to create buttons with various types of formatting: <Button> <StackPanel Orientation="Horizontal"> <TextBlock>Formatted </TextBlock> <TextBlock Foreground="Blue" FontWeight="Bold" Margin="2,0">Button</TextBlock> <TextBlock Foreground="Gray" FontStyle="Italic">[Various]</TextBlock> </StackPanel> </Button> But of course, you are not limited to just text - you can put whatever you want inside your buttons, which leads us to a subject that I know many people will ask for. Buttons with images! 122 Buttons with Images (ImageButton) In many UI frameworks, you will find a regular Button and then one or several other variants, which will offer extra features. One of the most commonly used variants is the ImageButton, which, as the name implies, is a Button which will usually allow you to include an image before the text. But in WPF, there's no need for a separate control to accomplish this - as you just saw, we can put several controls inside a Button, so you can just as easily add an Image control to it, like this: <Button Padding="5"> <StackPanel Orientation="Horizontal"> <Image Source="/WpfTutorialSamples;component/Images/help.png" /> <TextBlock Margin="5,0">Help</TextBlock> </StackPanel> </Button> It's really that simple to create an ImageButton in WPF, and you are of course free to move things around, e.g. if you want the image after the text instead of before etc. Button Padding You may have noticed that buttons in the WPF framework doesn't come with any padding by default. This means that the text is very close to the borders, which might look a little bit strange, because most buttons found elsewhere (web, other applications etc.) do have at least some padding in the sides. No worries, because the Button comes with a Padding property: <Button Padding="5,2">Hello, World!</Button> This will apply a padding of 5 pixels on the sides, and 2 pixels in the top and bottom. But having to apply padding to all of your buttons might get a bit tiresome at a certain point, so here's a small tip: You can apply the padding globally, either across the entire application or just this specific Window, using a Style (more on styles later). Here's an example where we apply it to the Window, using the Window.Resources property: <Window.Resources> <Style TargetType="{x:Type Button}"> <Setter Property="Padding" Value="5,2"/> </Style> </Window.Resources> 123 This padding will now be applied to all your buttons, but you can of course override it by specifically defining the Padding property on a Button. Here's how all the buttons of this example look with the common padding: The CheckBox control The CheckBox control allows the end-user to toggle an option on or off, usually reflecting a Boolean value in the Code-behind. Let's jump straight into an example, in case you're not sure how a CheckBox looks: <Window x:Class="WpfTutorialSamples.Basic_controls.CheckBoxSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="CheckBoxSample" Height="140" Width="250"> <StackPanel Margin="10"> <Label FontWeight="Bold">Application Options</Label> <CheckBox>Enable feature ABC</CheckBox> <CheckBox IsChecked="True">Enable feature XYZ</CheckBox> <CheckBox>Enable feature WWW</CheckBox> </StackPanel> </Window> As you can see, the CheckBox is very easy to use. On the second CheckBox, I use the IsChecked property to have it checked by default, but other than that, no properties are needed to use it. The IsChecked property should also be used from Code-behind if you want to check whether a certain CheckBox is checked or not. 124 Custom content The CheckBox control inherits from the ContentControl class, which means that it can take custom content and display next to it. If you just specify a piece of text, like I did in the example above, WPF will put it inside a TextBlock control and display it, but this is just a shortcut to make things easier for you. You can use any type of control inside of it, as we'll see in the next example: <Window x:Class="WpfTutorialSamples.Basic_controls.CheckBoxSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="CheckBoxSample" Height="140" Width="250"> <StackPanel Margin="10"> <Label FontWeight="Bold">Application Options</Label> <CheckBox> <TextBlock> Enable feature <Run Foreground="Green" FontWeight="Bold">ABC</Run> </TextBlock> </CheckBox> <CheckBox IsChecked="True"> <WrapPanel> <TextBlock> Enable feature <Run FontWeight="Bold">XYZ</Run> </TextBlock> <Image Source="/WpfTutorialSamples;component/Images/question.png" Width="16" Height="16" Margin="5,0" /> </WrapPanel> </CheckBox> <CheckBox> <TextBlock> Enable feature <Run Foreground="Blue" TextDecorations="Underline" FontWeight="Bold">WWW</Run> </TextBlock> </CheckBox> </StackPanel> </Window> As you can see from the sample markup, you can do pretty much whatever you want with the content. On all three check boxes, I do something differently with the text, and on the middle one I even throw in an Image control. By specifying a control as the content, instead of just text, we 125 get much more control of the appearance, and the cool thing is that no matter which part of the content you click on, it will activate the CheckBox and toggle it on or off. The IsThreeState property As mentioned, the CheckBox usually corresponds to a boolean value, which means that it only has two states: true or false (on or off). However, since a boolean data type might be nullable, effectively allowing for a third option (true, false or null), the CheckBox control can also support this case. By setting the IsThreeState property to true, the CheckBox will get a third state called "the indeterminate state". A common usage for this is to have a "Enable all" CheckBox, which can control a set of child checkboxes, as well as show their collective state. Our example shows how you may create a list of features that can be toggled on and off, with a common "Enable all" CheckBox in the top: XAML: <Window x:Class="WpfTutorialSamples.Basic_controls.CheckBoxThreeStateSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="CheckBoxThreeStateSample" Height="170" Width="300"> <StackPanel Margin="10"> <Label FontWeight="Bold">Application Options</Label> <StackPanel Margin="10,5"> <CheckBox IsThreeState="True" Name="cbAllFeatures" Checked="cbAllFeatures_CheckedChanged" Unchecked="cbAllFeatures_CheckedChanged">Enable all</CheckBox> <StackPanel Margin="20,5"> <CheckBox Name="cbFeatureAbc" Checked="cbFeature_CheckedChanged" Unchecked="cbFeature_CheckedChanged">Enable feature ABC</CheckBox> <CheckBox Name="cbFeatureXyz" IsChecked="True" Checked="cbFeature_CheckedChanged" Unchecked="cbFeature_CheckedChanged">Enable feature XYZ</CheckBox> <CheckBox Name="cbFeatureWww" Checked="cbFeature_CheckedChanged" Unchecked="cbFeature_CheckedChanged">Enable feature WWW</CheckBox> </StackPanel> </StackPanel> </StackPanel> </Window> C#: using System; using System.Windows; namespace WpfTutorialSamples.Basic_controls { public partial class CheckBoxThreeStateSample : Window { public CheckBoxThreeStateSample() 126 { InitializeComponent(); } private void cbAllFeatures_CheckedChanged(object sender, RoutedEventArgs e) { bool newVal = (cbAllFeatures.IsChecked == true); cbFeatureAbc.IsChecked = newVal; cbFeatureXyz.IsChecked = newVal; cbFeatureWww.IsChecked = newVal; } private void cbFeature_CheckedChanged(object sender, RoutedEventArgs e) { cbAllFeatures.IsChecked = null; if((cbFeatureAbc.IsChecked == true) && (cbFeatureXyz.IsChecked == true) && (cbFeatureWww.IsChecked == true)) cbAllFeatures.IsChecked = true; if((cbFeatureAbc.IsChecked == false) && (cbFeatureXyz.IsChecked == false) && (cbFeatureWww.IsChecked == false)) cbAllFeatures.IsChecked = false; } } } This example works from two different angles: If you check or uncheck the "Enable all" CheckBox, then all of the child check boxes, each representing an application feature in our example, is either checked or unchecked. It also works the other way around though, where checking or unchecking a child CheckBox affects the "Enable all" CheckBox state: If they are all checked or unchecked, 127 then the "Enable all" CheckBox gets the same state - otherwise the value will be left with a null, which forces the CheckBox into the indeterminate state. All of this behavior can be seen on the screenshots above, and is achieved by subscribing to the Checked and Unchecked events of the CheckBox controls. In a real world example, you would likely bind the values instead, but this example shows the basics of using the IsThreeState property to create a "Toggle all" effect. The RadioButton control The RadioButton control allows you to give your user a list of possible options, with only one of them selected at the same time. You can achieve the same effect, using less space, with the ComboBox control, but a set of radio buttons tend to give the user a better overview of the options they have. <Window x:Class="WpfTutorialSamples.Basic_controls.RadioButtonSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="RadioButtonSample" Height="150" Width="250"> <StackPanel Margin="10"> <Label FontWeight="Bold">Are you ready?</Label> <RadioButton>Yes</RadioButton> <RadioButton>No</RadioButton> <RadioButton IsChecked="True">Maybe</RadioButton> </StackPanel> </Window> All we do is add a Label with a question, and then three radio buttons, each with a possible answer. We define a default option by using the IsChecked property on the last RadioButton, which the user can change simply by clicking on one of the other radio buttons. This is also the property you would want to use from Code-behind to check if a RadioButton is checked or not. 128 RadioButton groups If you try running the example above, you will see that, as promised, only one RadioButton can be checked at the same time. But what if you want several groups of radio buttons, each with their own, individual selection? This is what the GroupName property comes into play, which allows you to specify which radio buttons belong together. Here's an example: <Window x:Class="WpfTutorialSamples.Basic_controls.RadioButtonSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="RadioButtonSample" Height="230" Width="250"> <StackPanel Margin="10"> <Label FontWeight="Bold">Are you ready?</Label> <RadioButton GroupName="ready">Yes</RadioButton> <RadioButton GroupName="ready">No</RadioButton> <RadioButton GroupName="ready" IsChecked="True">Maybe</RadioButton> <Label FontWeight="Bold">Male or female?</Label> <RadioButton GroupName="sex">Male</RadioButton> <RadioButton GroupName="sex">Female</RadioButton> <RadioButton GroupName="sex" IsChecked="True">Not sure</RadioButton> </StackPanel> </Window> With the GroupName property set on each of the radio buttons, a selection can now be made for each of the two groups. Without this, only one selection for all six radio buttons would be possible. Custom content The RadioButton inherits from the ContentControl class, which means that it can take custom content and display next to it. If you just specify a piece of text, like I did in the example above, WPF will put it inside a TextBlock control and display it, but this is just a shortcut to make things easier for you. You can use any type of control inside of it, as we'll see in the next example: <Window x:Class="WpfTutorialSamples.Basic_controls.RadioButtonCustomContentSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 129 Title="RadioButtonCustomContentSample" Height="150" Width="250"> <StackPanel Margin="10"> <Label FontWeight="Bold">Are you ready?</Label> <RadioButton> <WrapPanel> <Image Source="/WpfTutorialSamples;component/Images/accept.png" Width="16" Height="16" Margin="0,0,5,0" /> <TextBlock Text="Yes" Foreground="Green" /> </WrapPanel> </RadioButton> <RadioButton Margin="0,5"> <WrapPanel> <Image Source="/WpfTutorialSamples;component/Images/cancel.png" Width="16" Height="16" Margin="0,0,5,0" /> <TextBlock Text="No" Foreground="Red" /> </WrapPanel> </RadioButton> <RadioButton IsChecked="True"> <WrapPanel> <Image Source="/WpfTutorialSamples;component/Images/question.png" Width="16" Height="16" Margin="0,0,5,0" /> <TextBlock Text="Maybe" Foreground="Gray" /> </WrapPanel> </RadioButton> </StackPanel> </Window> Markup-wise, this example gets a bit heavy, but the concept is pretty simple. For each RadioButton, we have a WrapPanel with an image and a piece of text inside of it. Since we now take control of the text using a TextBlock control, this also allows us to format the text in any way we want to. For this example, I have changed the text color to match the choice. An Image control (read more about those later) is used to display an image for each choice. Notice how you can click anywhere on the RadioButton, even on the image or the text, to toggle it on, because we have specified it as content of the RadioButton. If you had placed it as a separate panel, next to the RadioButton, the user would have to click directly on the round circle of the RadioButton to activate it, which is less practical. 130 The PasswordBox control For editing regular text in WPF we have the TextBox, but what about editing passwords? The functionality is very much the same, but we want WPF to display something else than the actual characters when typing in a password, to shield it from nosy people looking over your shoulder. For this purpose, WPF has the PasswordBox control, which is just as easy to use as the TextBox. Allow me to illustrate with an example: <Window x:Class="WpfTutorialSamples.Basic_controls.PasswordBoxSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="PasswordBoxSample" Height="160" Width="300"> <StackPanel Margin="10"> <Label>Text:</Label> <TextBox /> <Label>Password:</Label> <PasswordBox /> </StackPanel> </Window> In the screenshot, I have entered the exact same text into the two text boxes, but in the password version, the characters are replaced with dots. You can actually control which character is used instead of the real characters, using the PasswordChar property: <PasswordBox PasswordChar="X" /> In this case, the character X will be used instead of the dots. In case you need to control the length of the password, there's a MaxLength property for you: <PasswordBox MaxLength="6" /> I have used both properties in this updated example: <Window x:Class="WpfTutorialSamples.Basic_controls.PasswordBoxSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="PasswordBoxSample" Height="160" Width="300"> <StackPanel Margin="10"> <Label>Text:</Label> <TextBox /> 131 <Label>Password:</Label> <PasswordBox MaxLength="6" PasswordChar="X" /> </StackPanel> </Window> Notice how the characters are now X's instead, and that I was only allowed to enter 6 characters in the box. 132 Course Materials: https://wpf-tutorial.com/ https://www.tutorialspoint.com/wpf/index.htm https://docs.microsoft.com/en-us/visualstudio/get-started/csharp/tutorial-wpf?view=vs-2019 Assessment and Activities: Create a form allowing you to add, subtract, divide and multiply numbers: Having created your window, first attach code to the buttons so that if you leave one of the numbers blank (or enter an invalid number) you get an error message: If, on the other hand, you enter valid numbers, you should see the answer appear in a label at the bottom of the window (set its Visibility property in XAML to Collapsed, then set it to Visiibility.Visible in code): 133 Module 5 ADO.Net and Exception Handling Overview: ADO.NET is a set of classes that allows you to connect and work with data sources like databases, excel file, access file, xml file, mysql, sql or notepad. To connect your application with different sources of database you need to know the right Data Provider. There are several Data Providers in ADO.NET that connects with different types of sources. Module Objectives: After successful Completion of this module, you should be able to: • • • Know how to use the basic ADO.Net insert values into them, query the tables, retrieve the results of the queries, and update the tables. Learn how to use simple statements and prepared statements, and you will see an example of a stored procedure. Learn how to perform transactions and how to catch exceptions and warnings. 134 What is ADO.Net? ADO.NET provides a bridge between the front end controls and the back end database. The ADO.NET objects encapsulate all the data access operations and the controls interact with these objects to display data, thus hiding the details of movement of data. The following figure shows the ADO.NET objects at a glance: The DataSet Class The dataset represents a subset of the database. It does not have a continuous connection to the database. To update the database a reconnection is required. The DataSet contains DataTable objects and DataRelation objects. The DataRelation objects represent the relationship between two tables. Following table shows some important properties of the DataSet class: Properties Description CaseSensitive Indicates whether string comparisons within the data tables are case-sensitive. Container Gets the container for the component. DataSetName Gets or sets the name of the current data set. DefaultViewManager Returns a view of data in the data set. DesignMode Indicates whether the component is currently in design mode. EnforceConstraints Indicates whether constraint rules are followed when attempting any update operation. 135 Events Gets the list of event handlers that are attached to this component. ExtendedProperties Gets the collection of customized user information associated with the DataSet. HasErrors Indicates if there are any errors. IsInitialized Indicates whether the DataSet is initialized. Locale Gets or sets the locale information used to compare strings within the table. Namespace Gets or sets the namespace of the DataSet. Prefix Gets or sets an XML prefix that aliases the namespace of the DataSet. Relations Returns the collection of DataRelation objects. Tables Returns the collection of DataTable objects. The following table shows some important methods of the DataSet class: Methods Description AcceptChanges Accepts all changes made since the DataSet was loaded or this method was called. BeginInit Begins the initialization of the DataSet. The initialization occurs at run time. Clear Clears data. Clone Copies the structure of the DataSet, including all DataTable schemas, relations, and constraints. Does not copy any data. Copy Copies both structure and data. CreateDataReader() Returns a DataTableReader with one result set per DataTable, in the same sequence as the tables appear in the Tables collection. CreateDataReader(DataTable[]) Returns a DataTableReader with one result set per DataTable. EndInit Ends the initialization of the data set. 136 Equals(Object) Determines whether the specified Object is equal to the current Object. Finalize Free resources and perform other cleanups. GetChanges Returns a copy of the DataSet with all changes made since it was loaded or the AcceptChanges method was called. GetChanges(DataRowState) Gets a copy of DataSet with all changes made since it was loaded or the AcceptChanges method was called, filtered by DataRowState. GetDataSetSchema Gets a copy of XmlSchemaSet for the DataSet. GetObjectData Populates a serialization information object with the data needed to serialize the DataSet. GetType Gets the type of the current instance. GetXML Returns the XML representation of the data. GetXMLSchema Returns the XSD schema for the XML representation of the data. HasChanges() Gets a value indicating whether the DataSet has changes, including new, deleted, or modified rows. HasChanges(DataRowState) Gets a value indicating whether the DataSet has changes, including new, deleted, or modified rows, filtered by DataRowState. IsBinarySerialized Inspects the format of the serialized representation of the DataSet. Load(IDataReader, LoadOption, DataTable[]) Fills a DataSet with values from a data source using the supplied IDataReader, using an array of DataTable instances to supply the schema and namespace information. Load(IDataReader, LoadOption, String[]) Fills a DataSet with values from a data source using the supplied IDataReader, using an array of strings to supply the names for the tables within the DataSet. Merge() Merges the data with data from another DataSet. This method has different overloaded forms. 137 ReadXML() Reads an XML schema and data into the DataSet. This method has different overloaded forms. ReadXMLSchema(0) Reads an XML schema into the DataSet. This method has different overloaded forms. RejectChanges Rolls back all changes made since the last call to AcceptChanges. WriteXML() Writes an XML schema and data from the DataSet. This method has different overloaded forms. WriteXMLSchema() Writes the structure of the DataSet as an XML schema. This method has different overloaded forms. The DataTable Class The DataTable class represents the tables in the database. It has the following important properties; most of these properties are read only properties except the PrimaryKey property: Properties Description ChildRelations Returns the collection of child relationship. Columns Returns the Columns collection. Constraints Returns the Constraints collection. DataSet Returns the parent DataSet. DefaultView Returns a view of the table. ParentRelations Returns the ParentRelations collection. PrimaryKey Gets or sets an array of columns as the primary key for the table. Rows Returns the Rows collection. 138 The following table shows some important methods of the DataTable class: Methods Description AcceptChanges Commits all changes since the last AcceptChanges. Clear Clears all data from the table. GetChanges Returns a copy of the DataTable with all changes made since the AcceptChanges method was called. GetErrors Returns an array of rows with errors. ImportRows Copies a new row into the table. LoadDataRow Finds and updates a specific row, or creates a new one, if not found any. Merge Merges the table with another DataTable. NewRow Creates a new DataRow. RejectChanges Rolls back all changes made since the last call to AcceptChanges. Reset Resets the table to its original state. Select Returns an array of DataRow objects. The DataRow Class The DataRow object represents a row in a table. It has the following important properties: Properties Description HasErrors Indicates if there are any errors. Items Gets or sets the data stored in a specific column. ItemArrays Gets or sets all the values for the row. Table Returns the parent table. The following table shows some important methods of the DataRow class: Methods AcceptChanges Description Accepts all changes made since this method was called. 139 BeginEdit Begins edit operation. CancelEdit Cancels edit operation. Delete Deletes the DataRow. EndEdit Ends the edit operation. GetChildRows Gets the child rows of this row. GetParentRow Gets the parent row. GetParentRows Gets parent rows of DataRow object. RejectChanges Rolls back all changes made since the last call to AcceptChanges. The DataAdapter Object The DataAdapter object acts as a mediator between the DataSet object and the database. This helps the Dataset to contain data from multiple databases or other data source. The DataReader Object The DataReader object is an alternative to the DataSet and DataAdapter combination. This object provides a connection oriented access to the data records in the database. These objects are suitable for read-only access, such as populating a list and then breaking the connection. DbCommand and DbConnection Objects The DbConnection object represents a connection to the data source. The connection could be shared among different command objects. The DbCommand object represents the command or a stored procedure sent to the database from retrieving or manipulating data. 140 ADO.Net on C# Connecting to a database Connection to a database requires a connection string. This string has the information about the server you're going to connect to, the database you will require, and the credentials that you can use to connect. Each database has its own properties including the server name and type. SqlConnection class represents a database connection. The following code creates a SqlConnection object by passing a SQL Server connection string. 1. using(SqlConnection conn = new SqlConnection()) { 2. conn.ConnectionString = "Server=[server_name];Database=[database_name];Trusted _Connection=true"; 3. // using the code here... 4. } In this connection string, 1. Server - Name of the server to connect to. 2. Database - This is the name of the database you're connecting to. In all of the databases, there are two types of login methods. Windows Authentication and Database Authentication. In Windows Authentication, the database is authenticated using the user's credentials from Windows (the OS), and in Database Authentication you the username and word, in order to connect to the database. Connection pools Connecting to a database, as already said, is a long process of opening the connection, closing the connection, and so on. To repeat this process for every single user in the application is not a good approach and will slow down the processes of code execution. So, in program executions, many such connections would be opened and closed and again opened that are identical. These processes are time-consuming and are the opposite of a good UX. In the .NET Framework, ADO.NET plays a part in this and minimizes the opening and closing process to make the program execution a bit faster by creating, what we call, a Connection Pool. This technique reduces the number of times the connection is opened, by saving the instance of the connection. For every new connection, it just looks for a connection already opened, and then if the connection exists, doesn't attempt to create a new connection, otherwise, it opens a new connection based on the connection string. It must be remembered that only the connections with the same configuration can be pooled. Any connection with even a single dissimilarity would require a new pool for itself. Generally, it is based on the ConnectionString of the connection. You can learn how that would differ by changing the values in the connection string. 141 An example from the MSDN documentation would be like: 1. using(SqlConnection connection = new SqlConnection( 2. "Integrated Security=SSPI;Initial Catalog=Northwind")) { 3. connection.Open(); 4. // Pool A is created. 5. } 6. using(SqlConnection connection = new SqlConnection( 7. "Integrated Security=SSPI;Initial Catalog=pubs")) { 8. connection.Open(); 9. // Pool B is created because the connection strings differ. 10. } 11. using(SqlConnection connection = new SqlConnection( 12. "Integrated Security=SSPI;Initial Catalog=Northwind")) { 13. connection.Open(); 14. // The connection string matches pool A. 15. } Why use "using" in code In C# there are some objects that use the resources of the system. That needs to be removed, closed, flushed and disposed of, and so on. In C# you can either write the code to create a new instance to the resource, use it, close it, flush it and dispose of it. Or on the other hand, you can simply just use this using statement block in which the object created is closed, flushed, and disposed of and the resources are then allowed to be used again by other processes. This ensures that the framework would take the best measures for each process. We could have done it using the simple line to line code like: 1. 2. 3. 4. 5. 6. 7. SqlConnection conn = new SqlConnection(); conn.ConnectionString = "connection_string"; conn.Open(); // use the connection here conn.Close(); conn.Dipose(); // remember, there is no method to flush a connection. This was minimized as: 1. using(SqlConnection conn = new SqlConnection()) { 2. conn.ConnectionString = "connection_string"; 3. conn.Open(); 4. // use the connection here 5. } 142 Once the code would step out of this block. The resources would be closed and disposed of on their own. The framework would take care of in the best way. Executing the Commands Once connected to the database, you can execute the set of commands that you're having and which would execute on the server (or the data provider) to execute the function you're trying to do, such as a query for data, insert the data, update records and so on and so forth. SQL has the basic syntax for the commands and in my opinion, has the simple syntax of commands and nearly human-understandable commands in the programming world. In the namespace the class, SqlCommand does this job for us. An example of a command would be like: 1. SqlCommand command = new SqlCommand("SELECT * FROM TableName", conn); Each and every command on the SQL Server would be executed like this. The first parameter is the command and the second one is the connection on which the command would execute. You can any command into it and the underlying code would convert it back to the command that would execute on the server where the data is present and then will return the result to you, whether an error or a success report. Sometimes you might want to use the command of the INSERT INTO clause. To work that out, you will need to add parameters to the command, so that your database is safe from SQL Injections. Using parameters would reduce the chances of your database being attacked, by throwing an error if the user tries to add some commands (using the form) into the database server. Parameterizing the data Parameterizing the query is done using the SqlParameter ed into the command. For example, you might want to search for the records where the criteria match. You can denote that criteria, by ing the variable name into the query and then adding the value to it using the SqlParameter object. For instance, the following is your SqlCommand to be ed on to the server: 1. // Create the command 2. SqlCommand command = new SqlCommand("SELECT * FROM TableName WHERE Fi rstColumn = @0", conn); 3. // Add the parameters. 4. command.Parameters.Add(new SqlParameter("0", 1)); In the preceding code, the variable added is 0 and the value to it is ed. You can use any variable but it must start with a @ sign. Once that has been done, you can then add the parameters to that name. In this case, the value 1 has been hardcoded and you can add a variable value here too. 143 Remember, the connection must be opened in order to run this code, you can use conn.Open() to open the connection if asked. As explained in the code, I have used the parameter as a number (0) that can also be a name. For example, you can also write the code as: 1. // Create the command 2. SqlCommand command = new SqlCommand("SELECT * FROM TableName WHERE Fi rstColumn = @firstColumnValue", conn); 3. // Add the parameters. 4. command.Parameters.Add(new SqlParameter("firstColumnValue", 1)); This way, it will be easier for you to keep them in mind. I am better at working with numbers and indexes like in an array so I used 0, you can use a name, a combination of alphanumeric characters, and so on. Just the name in the SqlParameter object and you'll be good to go! Reading the data returned In SQL you usually use the SELECT statement to get the data from the database to show, CodeProject would do so to show the recent articles from their database, Google would do so to index the results, and so on. But how to show those data results in the application using C#? That is the question here. Well, in the namespace we're talking about, there is the class SqlDataReader present for the SqlCommand that returns the Reader object for the data. You can use this to read through the data and for each of the columns provide the results on the screen. The following code would get the results from the command once executed: 1. // Create a new SqlDataReader object and read data from the command. 2. using(SqlDataReader reader = command.ExecuteReader()) { 3. while there is another record present 4. while (reader.Read()) { 5. // write the data on to the screen 6. Console.WriteLine(String.Format("{0} \t | {1} \t | {2} \t | {3}", 7. // call the objects from their index 8. reader[0], reader[1], reader[2], reader[3])); 9. } 10. } This is the same code, it will execute, and once done executing it will let the framework handle the job and close the resources depending on the best method. 144 Adding data to the SQL Server A similar method is implemented for adding the data to the database. Only the command would change and we know in the database, the INSERT INTO clause is used to add the data. So, the command would become: 1. SqlCommand insertCommand = new SqlCommand("INSERT INTO TableName (FirstCo lumn, SecondColumn, ThirdColumn, ForthColumn) VALUES (@0, @1, @2, @3)", conn) ; You can then use the SqlParameter objects to add the values to the parameters. This way, when the command is executed the data would be added to the table that you've specified. Catching the errors from SQL Server SQL Server generates the errors for you to catch and work on them. In the namespace we're working on there are two classes that work with the errors and exceptions thrown by SQL Server. 1. SqlError 2. SqlException These are used to get the error details or to catch the exceptions in the code and print the data results respectively. If you're going to use a try-catch block you're more likely to use the SqlException thing in your code. For this to work, we will a command that we know will throw an error. 1. SqlCommand errorCommand = new SqlCommand("SELECT * FROM someErrorColum n", conn); Now we know that this is faulty, but this won't generate any error, untill we execute it. To do so, we will try to execute it like this: 1. errorCommand.ExecuteNonQuery(); Once this is executed, SQL Server would complain, saying there is no such table present. To catch it you can simply use the try-catch block with the SqlException in the catch block to be caught. For a working code, you can see the following code block in the live example of my article. That explains the usage of the try-catch block with the SqlException here. 145 Working example In the article, there is an associated example for you to download if you want to work it out. You must use a SQL Server, database, and the relevant tables to ensure the program works. If the server name does not match the database name or the tables then the program won't run. There was no way for me to attach a database in the example. Since the databases require a SQL Server database that will be always available using a connection, I won't use this database again, so I have not provided the database connection string. Database table The database table in my system was like the following, SELECT without WHERE You can run the console and you'll see the results on your screen. This is the code where the SELECT query ran and the output of the columns returned was printed. 146 SELECT with a WHERE We can at the same time add a few more parameters to the SELECT query so that only the data we want would be extracted from the database. For example, if we add a WHERE clause to the SELECT query, the following result would be generated. Inserting the data Once done, you can move on to the next stage. This part is related to the second command, where we add the records to the table. This statement, when executed, would add the data to the table. The table is now like this: In this example, what happens is that the preceding code is used in our application. I will also provide the code used in this console application. Comments have been added with each block so you understand how the code works. 147 Source code 1. using System; 2. using System.Data; 3. using System.Data.SqlClient; 4. using System.Collections.Generic; 5. using System.Linq; 6. using System.Text; 7. using System.Threading.Tasks; 8. 9. namespace SqlTest_CSharp { 10. class Program { 11. static void Main(string[] args) { 12. // Create the connection to the resource! 13. // This is the connection, that is established and 14. // will be available throughout this block. 15. using(SqlConnection conn = new SqlConnection()) { 16. // Create the connectionString 17. // Trusted_Connection is used to denote the connection uses Wi ndows Authentication 18. conn.ConnectionString = "Server=[server_name];Database=[databa se_name];Trusted_Connection=true"; 19. conn.Open(); 20. // Create the command 21. SqlCommand command = new SqlCommand("SELECT * FROM TableName W HERE FirstColumn = @0", conn); 22. // Add the parameters. 23. command.Parameters.Add(new SqlParameter("0", 1)); 24. 25. /* Get the rows and display on the screen! 26. * This section of the code has the basic code 27. * that will display the content from the Database Table 28. * on the screen using a SqlDataReader. */ 29. 30. using(SqlDataReader reader = command.ExecuteReader()) { 31. Console.WriteLine("FirstColumn\tSecond Column\t\tThird Col umn\t\tForth Column\t"); 32. while (reader.Read()) { 33. Console.WriteLine(String.Format("{0} \t | {1} \t | {2} \t | {3}", 34. reader[0], reader[1], reader[2], reader[3])); 35. } 36. } 37. Console.WriteLine("Data displayed! Now press enter to move to the next section!"); 38. Console.ReadLine(); 39. Console.Clear(); 40. 148 41. /* Above code was used to display the data from the Database t able! 42. 43. * This following section explains the key features to use * to add the data to the table. This is an example of another 44. * SQL Command (INSERT INTO), this will teach the usage of par ameters and connection.*/ 45. 46. 47. 48. 49. 50. 51. Console.WriteLine("INSERT INTO command"); // Create the command, to insert the data into the Table! // this is a simple INSERT INTO command! SqlCommand insertCommand = new SqlCommand("INSERT INTO TableNa me (FirstColumn, SecondColumn, ThirdColumn, ForthColumn) VALUES (@0, @1, @2, @ 3)", conn); 52. 53. // In the command, there are some parameters denoted by @, you can 54. // change their value on a condition, in my code, they're hardcoded. 55. 56. 57. insertCommand.Parameters.Add(new SqlParameter("0", 10)); insertCommand.Parameters.Add(new SqlParameter("1", "Test Colum n")); 58. insertCommand.Parameters.Add(new SqlParameter("2", DateTime.No w)); 59. 60. 61. insertCommand.Parameters.Add(new SqlParameter("3", false)); // Execute the command and print the values of the columns affected through 62. // the command executed. 63. 64. Console.WriteLine("Commands executed! Total rows affected are " + insertCommand.ExecuteNonQuery()); 65. Console.WriteLine("Done! Press enter to move to the next step" ); 66. Console.ReadLine(); 67. Console.Clear(); 68. 69. /* In this section, there is an example of the Exception case 70. * Thrown by the SQL Server, that is provided by SqlException 71. * Using that class object, we can get the error thrown by SQL Server. 72. 73. 74. * In my code, I am simply displaying the error! */ Console.WriteLine("Now the error trial!"); 149 75. 76. 77. // try block try { // Create the command to execute! With the wrong name of t he table (Depends on your Database tables) 78. SqlCommand errorCommand = new SqlCommand("SELECT * FROM so meErrorColumn", conn); 79. // Execute the command, here the error will pop up! 80. // But since we're catching the code block's errors, it wi ll be displayed inside the console. 81. errorCommand.ExecuteNonQuery(); 82. } 83. // catch block 84. catch (SqlException er) { 85. // Since there is no such column as someErrorColumn (Depen ds on your Database tables) 86. // SQL Server will throw an error. 87. Console.WriteLine("There was an error reported by SQL Serv er, " + er.Message); 88. } 89. } 90. // Final step, close the resources flush to dispose of them. ReadLine to prevent the console from closing. 91. Console.ReadLine(); 92. } 93. } 94. } Exception Handling in C# Exception handling in C#, supported by the try catch and finally block is a mechanism to detect and handle run-time errors in code. The .NET framework provides built-in classes for common exceptions. The exceptions are anomalies that occur during the execution of a program. They can be because of user, logic or system errors. If a user (programmer) does not provide a mechanism to handle these anomalies, the .NET runtime environment provides a default mechanism, which terminates the program execution. try..catch..finally C# provides three keywords try, catch and finally to implement exception handling. The try encloses the statements that might throw an exception whereas catch handles an exception if one exists. The finally can be used for any cleanup work that needs to be done. 150 Try..catch..finally block example: 1. try 2. { 3. // Statement which can cause an exception. 4. } 5. catch(Type x) 6. { 7. // Statements for handling the exception 8. } 9. finally 10. { 11. //Any cleanup code 12. } If any exception occurs inside the try block, the control transfers to the appropriate catch block and later to the finally block. But in C#, both catch and finally blocks are optional. The try block can exist either with one or more catch blocks or a finally block or with both catch and finally blocks. If there is no exception occurred inside the try block, the control directly transfers to finally block. We can say that the statements inside the finally block is executed always. Note that it is an error to transfer control out of a finally block by using break, continue, return or goto. In C#, exceptions are nothing but objects of the type Exception. The Exception is the ultimate base class for any exceptions in C#. The C# itself provides couple of standard exceptions. Or even the user can create their own exception classes, provided that this should inherit from either Exception class or one of the standard derived classes of Exception class like DivideByZeroExcpetion to ArgumentException etc. Uncaught Exceptions The following program will compile but will show an error during execution. The division by zero is a runtime anomaly and program terminate with an error message. Any uncaught exceptions in the current context propagate to a higher context and looks for an appropriate catch block to handle it. If it can't find any suitable catch blocks, the default mechanism of the .NET runtime will terminate the execution of the entire program. 1. 2. 3. 4. 5. 6. 7. 8. 9. //C#: Exception Handling //Author: rajeshvs@msn.com using System; class MyClient { public static void Main() { int x = 0; int div = 100/x; 151 10. 11. 12. } Console.WriteLine(div); } The modified form of the above program with exception handling mechanism is as follows. Here we are using the object of the standard exception class DivideByZeroException to handle the exception caused by division by zero. 1. //C#: Exception Handling 2. using System; 3. class MyClient 4. { 5. public static void Main() 6. { 7. int x = 0; 8. int div = 0; 9. try 10. { 11. div = 100 / x; 12. Console.WriteLine("This linein not executed"); 13. } 14. catch (DivideByZeroException) 15. { 16. Console.WriteLine("Exception occured"); 17. } 18. Console.WriteLine($"Result is {div}"); 19. } 20. } Result from above code is show below: 152 In the above case, the program does not terminate unexpectedly. Instead, the program control passes from the point where exception occurred inside the try block to the catch blocks. If it finds any suitable catch block, executes the statements inside that catch and continues with the normal execution of the program statements. If a finally block is present, the code inside the finally block will get also be executed. 1. //C#: Exception Handling 2. using System; 3. class MyClient 4. { 5. public static void Main() 6. { 7. int x = 0; 8. int div = 0; 9. try 10. { 11. div = 100/x; 12. Console.WriteLine("Not executed line"); 13. } 14. catch(DivideByZeroException) 15. { 16. Console.WriteLine("Exception occured"); 17. } 18. finally 19. { 20. Console.WriteLine("Finally Block"); 21. } 22. Console.WriteLine($"Result is {div}"); 23. } 24. } Remember that in C#, the catch block is optional. The following program is perfectly legal in C#. 1. //C#: Exception Handling 2. using System; 3. class MyClient 4. { 5. public static void Main() 6. { 7. int x = 0; 8. int div = 0; 9. try 10. { 11. div = 100/x; 12. Console.WriteLine("Not executed line"); 13. } 14. finally 153 15. 16. 17. 18. 19. 20. } { Console.WriteLine("Finally Block"); } Console.WriteLine($"Result is {div}"); } But in this case, since there is no exception handling catch block, the execution will get terminated. But before the termination of the program statements inside the finally block will get executed. In C#, a try block must be followed by either a catch or finally block. Multiple Catch Blocks A try block can throw multiple exceptions, which can handle by using multiple catch blocks. Remember that more specialized catch block should come before a generalized one. Otherwise, the compiler will show a compilation error. 1. //C#: Exception Handling: Multiple catch 2. using System; 3. class MyClient 4. { 5. public static void Main() 6. { 7. int x = 0; 8. int div = 0; 9. try 10. { 11. div = 100 / x; 12. Console.WriteLine("Not executed line"); 13. } 14. catch (DivideByZeroException de) 15. { 16. Console.WriteLine("DivideByZeroException"); 17. } 18. catch (Exception) 19. { 20. Console.WriteLine("Exception"); 21. } 22. finally 23. { 24. Console.WriteLine("Finally Block"); 25. } 26. Console.WriteLine($"Result is {div}"); 27. } 28. } 154 Catching all Exceptions By providing a catch block without brackets or arguments, we can catch all exceptions occurred inside a try block. Even we can use a catch block with an Exception type parameter to catch all exceptions happened inside the try block since in C#, all exceptions are directly or indirectly inherited from the Exception class. 1. //C#: Exception Handling: Handling all exceptions 2. using System; 3. class MyClient 4. { 5. public static void Main() 6. { 7. int x = 0; 8. int div = 0; 9. try 10. { 11. div = 100 / x; 12. Console.WriteLine("Not executed line"); 13. } 14. catch 15. { 16. Console.WriteLine("oException"); 17. } 18. Console.WriteLine($"Result is {div}"); 19. } 20. } The following program handles all exception with Exception object. 1. //C#: Exception Handling: Handling all exceptions 2. using System; 3. class MyClient 4. { 5. public static void Main() 6. { 7. int x = 0; 8. int div = 0; 9. try 10. { 11. div = 100 / x; 12. Console.WriteLine("Not executed line"); 13. } 14. catch (Exception) 15. { 16. Console.WriteLine("oException"); 17. } 18. Console.WriteLine($"Result is {div}"); 155 19. 20. } } Throwing an Exception In C#, it is possible to throw an exception programmatically. The 'throw' keyword is used for this purpose. The general form of throwing an exception is as follows. 1. throw exception_obj; For example, the following statement throws an ArgumentException explicitly. 1. throw new ArgumentException("Exception"); 2. 3. //C#: Exception Handling: 4. using System; 5. class MyClient 6. { 7. public static void Main() 8. { 9. try 10. { 11. throw new DivideByZeroException("Invalid Division"); 12. } 13. catch (DivideByZeroException) 14. { 15. Console.WriteLine("Exception"); 16. } 17. Console.WriteLine("LAST STATEMENT"); 18. } 19. } Re-throwing an Exception The exceptions, which we caught inside a catch block, can re-throw to a higher context by using the keyword throw inside the catch block. The following program shows how to do this. 1. 2. 3. 4. 5. 6. //C#: Exception Handling: Handling all exceptions using System; class MyClass { public void Method() { 156 7. try 8. { 9. int x = 0; 10. int sum = 100 / x; 11. } 12. catch (DivideByZeroException) 13. { 14. throw; 15. } 16. } 17. } 18. class MyClient 19. { 20. public static void Main() 21. { 22. MyClass mc = new MyClass(); 23. try 24. { 25. mc.Method(); 26. } 27. catch (Exception) 28. { 29. Console.WriteLine("Exception caught here"); 30. } 31. Console.WriteLine("LAST STATEMENT"); 32. } 33. } Standard Exceptions There are two types of exceptions: exceptions generated by an executing program and exceptions generated by the common language runtime. System.Exception is the base class for all exceptions in C#. Several exception classes inherit from this class including ApplicationException and SystemException. These two classes form the basis for most other runtime exceptions. Other exceptions that derive directly from System.Exception include IOException, WebException etc. The common language runtime throws SystemException. The ApplicationException is thrown by a user program rather than the runtime. The SystemException includes the ExecutionEngineException, StaclOverFlowException etc. It is not recommended that we catch SystemExceptions nor is it good programming practice to throw SystemExceptions in our applications. • • • • System.OutOfMemoryException System.NullReferenceException Syste.InvalidCastException Syste.ArrayTypeMismatchException 157 • • • • System.IndexOutOfRangeException System.ArithmeticException System.DivideByZeroException System.OverFlowException User-defined Exceptions In C#, it is possible to create our own exception class. But Exception must be the ultimate base class for all exceptions in C#. So the user-defined exception classes must inherit from either Exception class or one of its standard derived classes. 1. //C#: Exception Handling: User defined exceptions 2. using System; 3. class MyException : Exception 4. { 5. public MyException(string str) 6. { 7. Console.WriteLine("User defined exception"); 8. } 9. } 10. class MyClient 11. { 12. public static void Main() 13. { 14. try 15. { 16. throw new MyException("RAJESH"); 17. } 18. catch (Exception) 19. { 20. Console.WriteLine("Exception caught here" + e.ToString()); 21. } 22. Console.WriteLine("LAST STATEMENT"); 23. } 24. } Design Guidelines Exceptions should be used to communicate exceptional conditions. Don't use them to communicate events that are expected, such as reaching the end of a file. If there's a good predefined exception in the System namespace that describes the exception condition-one that will make sense to the users of the class-use that one rather than defining a new exception class and put specific information in the message. Finally, if code catches an exception that it isn't going to handle, consider whether it should wrap that exception with additional information before rethrowing it. 158 Course Materials https://www.tutorialspoint.com/asp.net/asp.net_ado_net.htm https://www.c-sharpcorner.com/UploadFile/201fc1/sql-server-database-connection-in-csharpusing-adonet/ https://www.c-sharpcorner.com/article/exception-handling-in-C-Sharp/ Activities/Assessment 1. Using the table below, create a WPF Application that will manage employee records. 159 Module 6 Application Development Concepts Overview: To know the process of designing, building, and implementing software applications. To address the issues of developing an application and know the standards and guidelines for testing and implementing a java application. Module Objectives: After successful Completion of this module, you should be able to: • • • Know the definition of Application and Application development Explain the concepts of Application Development and Issues Apply the different level and kinds of test in the application developed. 160 What is an Application? An application is simply a computer-based model of some aspect of the real world designed to solve a specific set of problems. Computing technology has given rise to an ever-increasing number of applications in almost every aspect of life, from the most mundane address book s, to the information systems required to track the business processes of an entire enterprise. Regardless of the size or complexity of applications, they all have a common purpose: the manipulation, analysis, and persistence of data. What Is Application Development? Application development is the process of designing, building, and implementing software applications. It can be done by massive organizations with large teams working on projects, or by a single freelance developer. Application development defines the process of how the application is made, and generally follows a standard methodology. There are lots of factors that go into how application development is done. You must consider the size of the project, how specific the requirements are, how much the customer will want to change things, how large the development team is, how experienced the development team is, and the deadline for the project. Application development is closely linked with the software development life-cycle (SDLC). Identifying the Issues Given this general definition of an application, it is clear that data management plays a large role in any application. As such, every application must address at least some of the following issues: Persistence The data must be stored for an extended period of time. Integrity The data must be correct, according to some defined set of rules. Concurrency Coordinating read and change requests from multiple users. Scalability The application must scale in terms of number of users, volume of data, and data complexity. Performance Providing efficient access to the application data. Recovery Ensuring that the data can survive application and system failures. Security Preventing unauthorized access or manipulation of the application data. 161 Reporting Providing general analysis and presentation of the application data to support decision making within the organization. Integration Allowing the application to interact with other software systems. Presentation Providing a user interface for entry and manipulation of the application data. In addition to these problems, the application will inevitably encounter change of some form: Requirements Change Modifying the application to fit new or changing business needs. Environment Change Reacting to changes in the hardware or software environment. In building applications that handle all these issues, we also encounter development process issues that must be addressed: Developer Productivity Ensuring maximum productivity of application team members. Developer Training Training team members on the platforms and technologies to be used. Application Quality Ensuring the application meets requirements and functionality. Deployment Providing installation and deployment for the application. Maintenance Providing a maintenance path for deployed applications. Clearly, application development in general is an extremely complex problem. The more complex the application, the more difficult the solution to these problems becomes. Fortunately, these solutions can, for the most part, be generally implemented in systems -level software that all applications can utilize. Many of these issues, such as persistence, concurrency, scalability, and others, are already addressed to varying degrees by existing systems; however, there are still many issues that arise when developing applications against these systems: Schema Duplication Presentation layers often duplicate the structures and logic already present in the database schema. Complex Business Rules Existing systems often do not provide effective support for complex business rules. Client-Side Enforcement of Business Rules - Presentation layers must provide initial enforcement of business rules. 162 Client-Side Buffering Presentation layers must provide a mechanism for data retrieval, display, entry and translation. Traditionally, these problems have been resolved on a case-by-case basis within each application. The result is large amounts of application-specific code that is difficult to produce and maintain. If a general purpose solution to these issues can be found, it can be automated, just as many of the issues relating to data management have been automated by Database Management Systems (DBMSs). Various Software Testing Concepts Enlisted below are the various Software Testing Concepts along with their comparison. Difference Between Test Plan And Test Strategy Test Strategy and Test plan are two important documents in the testing life cycle of any project. Here we are trying to give you an in-depth knowledge of test strategy and test plan documents. Test Plan A Test Plan can be defined as a document that defines the scope, objective, and approach to test the software application. The Test Plan is a term and a deliverable. The Test Plan is a document that lists all the activities in a QA project, schedules them, defines the scope of the project, roles & responsibilities, risks, entry & exit criteria, test objective, and anything else that you can think of. The Test Plan is as I like to call a ‘super document’ that lists everything there is to know and need. Please check this link for more information and a sample. The Test Plan will be designed based on the requirements. While assigning work to the test engineers, due to some reasons one of the testers gets replaced by another one. Here, the Test Plan gets updated. The Test strategy outlines the testing approach and everything else that surrounds it. It is different from the Test Plan, in the sense that a Test strategy is only a subset of the test plan. It is a hardcore test document that is to an extent generic and static. There is also an argument about at what levels test strategy or plan is used- but I really do not see any discerning difference. Example: The Test Plan gives information about who is going to test at what time. For Example, Module 1 is going to be tested by “X tester”. If tester Y replaces X for some reason, the test plan has to be updated. Test Plan Document Test Plan is a document that provides complete information about testing tasks related to a Software Project. It provides details like Scope of the testing, Types of testing, Objectives, Test Methodology, Testing Effort, Risks & Contingencies, Release Criteria, Test Deliverables, etc. It keeps track of possible tests that will be run on the system after coding. The test plan is obviously set to change. Initially, a draft test plan will be developed based on project clarity at that time. This initial plan will get modified as the project progresses. Test team 163 Manager or Test Lead can prepare the test plan document. It describes the Specifications and is subject to change based on the same. What to test, when to test, who will test, and how to test will be defined in the test plan. Test Plan will sort out a list of issues, dependencies, and the underlying risks. Separate test plans can be created for specific testing types like system testing, system integration testing, user acceptance testing, etc. Another approach is to have separate test plans for functional and non-functional testing. In this approach performance, testing will have a separate test plan. Contents of Test plan Document (IEEE-829 test plan structure) It is difficult to draw a clear format for the test plan. The test plan format may vary depending on the project in hand. IEEE has defined a standard for test plans which are described as the IEEE829 test plan structure. Please find below IEEE recommendations for a standard test plan content: 1. Test Plan Identifier 2. Introduction 3. Test Items 4. Software Risk Issues 5. Features to be tested 6. Features not to be tested 7. Approach 8. Item Pass/Fail Criteria (or) Acceptance Criteria 9. Suspension Criteria and Resumption Requirements 10. Test Deliverables 11. Test Tasks 12. Environmental Requirements 13. Staffing and Training needs 14. Responsibilities 15. Schedule 16. Approvals Test Strategy Test Strategy is a set of guidelines that explain the test design and determine how testing needs to be done. Example: A Test Strategy includes details like “Individual modules are to be tested by the test team members”. In this case, who tests it does not matter – so it’s generic and the change in the team member does not have to be updated, keeping it static. Test Strategy Document The purpose of the test strategy is to define the testing approach, the types of tests, test environments, and tools to be used for testing and the high-level details of how the test strategy will be aligned with other processes. The test strategy document is intended to be a living document and will be updated** when we get more clarity on Requirements, SLA parameters, Test environment and Build management approach, etc. 164 Test strategy is intended for the complete project team that comprises of Project Sponsors, Business SMEs, Application/ Integration Development, System Integration partners, Data Conversion Teams, Build/Release Management Teams such as technical leads, architecture leads, and deployment and infrastructure teams. ** Some argue that test strategy once defined should never be updated. In most testing projects usually, it gets updated as the project progress. Below are the important sections that a test strategy document should have: #1) Project Overview This section can begin by giving an overview of the organization followed by a brief description of the project in hand. It can include below details • • What was the need for the project? What objectives the project will attain? Table of Acronyms: It is better to include a table with acronyms that the document reader might come up with while referring to the document. #2) Requirements Scope Requirement scope can include Application Scope and Functional scope Application Scope defines the system under test and the impact on the system due to new or changed functionality. Related systems can also be defined. System Impact (New or Changed functionality) Related System System A New enhancements and bug fixes • System B • System C Functional Scope defines the impact on different modules within the system. Here each related system with respect to functionality will be explained. System Module Functionality Related System System C Module 1 Functionality 1 System B Functionality 2 System C #3) High-Level Test Plan 165 Test Plan is a separate document. In the test strategy, a high-level test plan can be included. A high-level test plan can include test objectives and test scope. Test scope should define both in scope and out of scope activities. #4) Test Approach This section describes the testing approach that will be followed during the testing life cycle. As per the above diagram testing will be conducted in two phases i.e. Test Strategy & Planning and Test Execution. Test Strategy & Planning phase will be one time for an overall program whereas Test execution phases will be repeated for each Cycle of the overall program. The above diagram shows different stages and deliverables (outcome) in each phase of the execution approach. Test approach should include below sub-sections a) Test Schedule: Explain the proposed project timeline in this subsection b) Functional Testing Approach: Using this subsection provides an overview of each phase and the respective entry and exit criteria. Different testing phases are Unit testing, System testing, System Integration testing, User Acceptance Testing, and End-to-End testing. c) Testing Key Performance Indicators : • Test case prioritization: Define the test case prioritization approach so that in case of time constraints, high priority scenarios can be executed by the test team. There should be an agreement between project stakeholders regarding the possible risks involved in not executing all the planned scenarios. 166 • • Defect prioritization: Defect prioritization strategy is the next topic to cover here. Define priority level and give the description to each level like critical, high, medium, etc. Also Defect Turnaround Time: Defect turnaround time is defined as the time between when the defect was first raised and when the defect is fixed and comes for a retest. Quick turnaround ensures speedy testing and adherence to the project timeline. For each defect priority level, define the turnaround time. Priority Level Defect Turnaround Time 1 - Critical Response Time: 2 hours or less Fix Ready for Migration: 1 business days or less #5) Test Coverage This section describes the processes that the QA team will follow in order to optimize the coverage of business/functional requirements in test scenarios and test cases. Requirement Traceability Matrix: (RTM) can be used to trace all the requirements with respective test scenarios and test cases. #6) Test Environment Define the different QA environments available. Mention what testing will be done in which environment and by whom. Create an environment backup plan to take care of emergencies. Access to each environment should be regulated and called out with clarity. Testing tools that are going to be used also can be mentioned in this section. Activity Tool Remarks Test management HP ALM Mention the reason for using this tool Defect management JIRA Mention the reason for using this tool #7) QA Deliverables and Metrics List out all the QA deliverables S. No. Deliverable 1 Test Strategy Document 2 Requirement Traceability Matrix 3 ST Test Scripts 167 S. No. Deliverable 4 Test Summary Report 5 Automation eligible scenario list List out all the QA metrics Metric Reports in which unit of the metrics to be measure used Metric Definition Metric Formula Requirements Coverage Metrics(RCM) The coverage of requirements by QA Ratio of # of % requirements tested to # of requirements identified Weekly QA status report, Test summary report Test Coverage The coverage of test case executed Ratio of % number of test cases executed /number of test cases planned Daily Execution report, Weekly QA status report, Test summary report # Metric Name 1 2 #8) Defect Management Clearly define a defect management strategy by creating a defect workflow, defect tracking methodology & defect triage process. Mention defect responsibility for each tester's roles. Periodic defect analysis and root cause analysis will improve the overall quality of testing #9) Communication Management Set guidelines for status reports, status meetings, and onsite-offshore communication. #10) Assumptions, Risks, and Dependencies 168 Describe assumptions on which the project is based. These may include timing, resources, and system capabilities. Describe any dependencies such as other projects, availability of temporary resources, other deadlines that may impact the project. #11) Appendix Include stuff like Roles & Responsibilities, Work Time Zone, and References in this section Further reading => Guide to Writing a Good Test Strategy document. Test Plan Vs Test Strategy TEST PLAN TEST STRATEGY It is derived from software requirement specification(SRS). It is derived from the Business Requirement document(BRS). It is prepared by the test lead or manager. It is developed by the project manager or the Business analyst. Test plan id, features to be tested, test techniques, testing tasks, features pass or fail criteria, test deliverables, responsibilities, and schedule, etc. are the components of the test plan. Objectives and scope, documentation formats, test processes, team reporting structure, client communication strategy, etc. are the components of test strategy. If there is a new feature or a change in the requirement that is happened then the test plan document gets updated. Test strategy maintains the standards while preparing the document. It is also called as Static document. We can prepare the test plan individually. In smaller projects, test strategy is often found as a section of a test plan. We can prepare a Test plan at the project level. We can use Test strategy at multiple projects. It describes how to test , when to test, who will test and what to test. It describes what type of technique to follow and which module to test. We can describe about the specifications by using a Test Plan. Test strategy describes about the general approaches. Test Plan will change over the course of the project. Test Strategy usually will not change once approved. 169 TEST PLAN TEST STRATEGY Test plan is written after requirement sign off. Test strategy is made before the test plan. Test plans can be of different types. There will be a master test plan and separate test plan for different types of testing like system test plan, performance test plan, etc. There will be only one test strategy document for a project. Test plan should be clear and concise. Test strategy provides overall guidance for the project in hand. The difference between these two documents is subtle. A test strategy is a high-level static document about the project. On the other hand, the test plan will specify what to test, when to test, and how to test. Difference Between Test Case And Test Script In my opinion, these two terms can be used interchangeably. Yes, I am saying there is no difference. The test case is a sequence of steps that help us perform a certain test on the application. The test script is also the same thing. TEST CASE TEST SCRIPT It is a step by step by procedure that is used to test an application It is a set of instructions to test an application automatically. The term Test Case is used in the manual testing environment. The term Test Script is used in automation testing environment. It is done manually. It is done by scripting format. It is developed in the form of templates. It is developed in the form of scripting. Test case template includes Test Suit ID, Test Data, Test procedure, Actual results, Expected results etc. In Test Scrip,t we can use different commands to develop script. 170 Now, is one Is used to test an application. It is also used to test an application. It is the base form to test an application in sequence. Once we develop, the script will run it multiple times until the requirement is changed. Example: We need to verify the login button in an application, The steps include: a) Launch the application. b) Verify if the login button is displaying or not. Example: We want to click an image button in an application. The script includes: a) Click the Image Button. there school of thought that a test case is a term used in the manual testing environment and test script is used in an automation environment. This is partly true, because of the comfort level of the testers in the respective fields and also on how the tools refer to the tests (some call test scripts and some call them to test cases). So in effect, test script and test case both are steps to be performed on an application to validate its functionality whether manually or through automation. Difference Between Test Scenario and Test Condition Test Scenario: It is a way to define all the possible ways to test an application. It is a single statement to cover all possible ways to test an application. Test Condition: Test Condition is the specification that a tester must follow for testing an Application. This is a one-line pointer that testers create as an initial, transitional step into the test design phase. This is mostly a one-line definition of “What” we are going to test with respect to a certain feature. Usually, test scenarios are input for the creation of test cases. In agile projects, Test scenarios are the only test design outputs and no test cases are written following these. A Test scenario might result in multiple tests. Examples of Test Scenarios: • • • Validate if a new country can be added by the Admin Validate if an existing country can be deleted by the Admin Validate if an existing country can be updated Test conditions, on the other hand, are more specific. It can be roughly defined as the aim/goal of a certain test. 171 Example Test Condition: In the above example, if we were to test the scenario 1, we can test the following conditions: • • • Enter the country name as “India”(valid )and check for the addition of the country Enter a blank and check if the country gets added. In each case, the specific data is described and the goal of the test is much more precise. TEST SCENARIO TEST CONDITION It is a process to test an application with all possible ways. Test conditions are the static rules should be followed to test an application. Test scenarios are an input for the creation of test cases. It gives the main goal to test an application. Test scenario covers all possible cases to test an application. Test condition is very specific. It reduces the complexity. It makes a system bug free. Test scenario can be a single or a group of test cases. It is the goal of test cases. By writing scenarios it will be easy to understand the functionality of an application. Test condition is very specific. These are one line statements to explain what we are going to test. Test Condition describes the main goal to test an application. Examples test scenarios: #1) Validate if a new country can be added by the Admin. #2) Validate if an existing country can be deleted by the admin. #3) Validate if an existing Country can be updated. Examples test Conditions: #1) Enter the country name as “India” and check for the addition of the country. #2) Leave blank fields and check if the country gets added. 172 Difference Between Test Procedure and Test Suite The test procedure is a combination of test cases based on a certain logical reason, like executing an end-to-end situation or something to that effect. The order in which the test cases are to be run is fixed. Test Procedure: It is nothing but the Test Life Cycle. There are 10 steps in the Testing Life Cycle. They are: 1. Effort Estimation 2. Project Initiation 3. System Study 4. Test plan 5. Design Test Case 6. Test Automation 7. Execute Test Cases 8. Report Defects 9. Regression Testing 10. Analysis and Summary Report The order of test cases that will combine to form a test procedure would be: 1. 2. 3. 4. 5. 6. The test to check the login The test to compose an email The test to attach one/more attachments Formatting the email in the required way by using various options Adding contacts or email addresses to the To, BCC, CC fields Sending an email and making sure it is showing in the “Sent Mail” section All the test cases above are grouped to achieve a certain target at the end of them. Also, test procedures have a few test cases combined at any point in time. The Test suite, on the other hand, is the list of all the test cases that have to be executed as a part of a test cycle or a regression phase, etc. There is no logical grouping based on functionality. The order in which the constituent test cases get executed may or may not be important. Test Suite: The Test Suite is a container that has a set of tests which help the testers in executing and reporting the test execution status. It can take any of the three states i.e. Active, in progress and completed. Example of the Test Suite: If an application’s current version is 2.0. The previous version 1.0 might have had 1000 test cases to test it entirely. For version 2 there are 500 test cases to just test the new functionality that is added in the new version. So, the current test suite would be 1000+500 test cases that include both regression and the new functionality. The suite is a combination too, but we are not trying to achieve a target function. Test suites can contain 100s or even 1000s of test cases. 173 TEST PROCEDURE TEST SUITE It is a combination of test cases to test an application. It is a group of test cases to test an application. It is a logical grouping based on the functionality. There is no logical grouping based on the functionality. Test Procedures are deliverable products in the software development process. It is executed as a part of the test cycle or regression. The order of execution is fixed. The order of execution may not be important. Test procedure contains end to end test cases. Test suite contains all new features and regression test cases. Test procedures are coded in a new language called TPL(Test Procedure language). Test suite contains manual test cases or automation scripts. Creation of Test Procedures is based on the end to end test flow. Test suites are created based on the cycle or based on the scope. Unit Testing Writing a test case is always an important part of software testing. Testing software is always a real challenges for developers and testers, because many types of test cases exists and also come in so many different shapes and sizes. In order to learn how to write good test cases, we must first understand what is a test case and why do we need it. Later we will learn how to write Unit Test using C# language. So let's learn that first What do you mean by a Unit test ? In the software development process Unit Tests basically test individual parts ( also called as Unit ) of code (mostly methods) and make it work as expected by programmer. A Unit Test is a code written by any programmer which test small pieces of functionality of big programs. Performing unit tests is always designed to be simple, A "UNIT" in this sense is the smallest component of the large code part that makes sense to test, mainly a method out of many methods of some class. Generally the tests cases are written in the form of functions that will evaluate and determine whether a returned value after performing Unit Test is equals to the value you were 174 expecting when you wrote the function. The main objective in unit testing is to isolate a unit part of code and validate its to correctness and reliable. Why do we need Unit test? One of the most valuable benefits of using Unit Tests for your development is that it may give you positive confidence that your code will work as you have expected it to work in your development process. Unit Tests always give you the certainty that it will lead to a long term development phase because with the help of unit tests you can easily know that your foundation code block is totally dependable on it. There are few reasons that can give you a basic understanding of why a developer needs to design and write out test cases to make sure major requirements of a module are being validated during testing, • • • • • Unit testing can increase confidence and certainty in changing and maintaining code in the development process. Unit testing always could find problems in early stages in the development cycle. Codes are more reusable, reliable, and clean. Development becomes faster. Easy to automate. Let us start the show – create your first Unit test (step by Step) Unit testing is a way or you can say that process with the help of this a programmer can make themselves sure that their code that is written is fully functional, clean, reliable and will definitely work the same way as it is supposed to work. One of the fundamental principles of adopting unit testing is to follow a TDD (Test Driven Development) aproach where we have to write tests case first, and then write the simple code that will make the test pass. Here I am going to follow just the opposite approach to make you learn how to write and Test code first with a simple example. Later we will discuss about TDD(Test Driven Development) concept. In this article we are going to follow different approach where we will write simple code first, and then create the Unit Tests based on the possible situations. As discussed earlier, we can also write Tests first, and then write the code that will make the test pass. It depends upon individuals what and which one of the ways they love to follow to test code. Here I’ve written a basic program which can be easily understandable by any novice who has just started to learn C# and wants to learn how to write unit tests. 1. public class BasicMaths { 2. public double Add(double num1, double num2) { 3. return num1 + num2; 4. } 5. public double Substract(double num1, double num2) { 175 6. 7. 8. 9. 10. 11. 12. return num1 - num2; } public double divide(double num1, double num2) { return num1 / num2; } public double Multiply(double num1, double num2) { // To trace error while testing, writing + operator instead of * opera tor. 13. return num1 + num2; 14. } 15. } In this program, you can see that there are four basic math functions: Add, Subtract, Divide and Multiply. All the functions have two double datatype parameters. MS Unit tests To test the above four methods, we are going to use Microsoft Testing tools, which is MS Unit Test. To add MS Unit Test, follow the steps given below. 176 First move to Solution Explorer ( shortcut Ctrl + Alt + L to open Solution Explorer). • • • Right click on Solution Project Name. Click Add. Click New Project. It will open Add New Project Window. Follow the given steps to create and add Unit Test Project. • • • Click Test. Select Unit Test Project from the list of the available templates. Write the name of the project. Here, we are using BasicMathTest followed by clicking OK button. It created BasicMathTest project along with BasicMath Project whose functions need to be tested. To access all the four methods of BasicMath in test project, we need to add the reference in test project. Take a look at the image given below to know how to add. 177 • • Right click on Reference of MS Unit Test Project. Click Add Reference. It will open a Reference Manager Window. To add reference, click Projects – Solutions – BasicMaths and click OK button. You can see in the image given below that the reference has been added . • • BasicMath – Having all the functions, which needs to be tested Microsoft.VisualStudio.QualityTools.UnitTestFramework – It contains all classes and methods, which provides Unit testing support. Great, you will get a screen, as shown below. 178 1. using System; 2. using Microsoft.VisualStudio.TestTools.UnitTesting; 3. namespace BasicMathTest { 4. [TestClass] 5. public class UnitTest1 { 6. [TestMethod] 7. public void TestMethod1() { 8. // TODO : Write test code 9. } 10. } 11. } What will we do next is add our code to test the functions of BasicMath Project. First add namespaces. 1. using System; 2. using Microsoft.VisualStudio.TestTools.UnitTesting; 3. using BasicMath; System namespace contains fundamental classes and base classes, which defines the commonly-used value and reference data types, events and event handlers, interfaces, attributes and processing exceptions. The Microsoft.VisualStudio.TestTools.UnitTesting namespace supplies the classes, which provides Unit testing support. This namespace contains many attributes, which identifies test information to the test the engine regarding the data sources, order of method execution, program management, agent/host information and the deployment of the data. Microsoft.VisualStudio.TestTools.UnitTesting namespace also contains custom unit testing exceptions. BasicMath namespace contains all the functions, which are required to be tested like Add, Subtract, Multiply and Divide Some requirements that need to be followed, Test class requirements The minimum requirements for a test class while writing Unit Test case is given below: • • If you are using Unit Test to write test case then the [TestClass] attribute is highly required in the Microsoft unit testing framework for any class that contains unit test methods that you would like to run in Visual Studio Test Explorer. Each and every test method that you want to run must having the [TestMethod]attribute above it. 179 Test method requirements A test method must meet the given requirements: • • • The method must be defined with the [TestMethod] attribute just above method name. The method must having return type void. The method cannot have any parameters. Writing first Unit Test method Here, we will write Unit Test methods to verify the behavior of Add method of the BasicMaths class. The code will look, as shown below. In a similar way, write test code for all the methods like Subtract, Multiply and Divide. After adding all the required test methods, our test code will look, as shown below. 1. [TestClass] 2. public class UnitTest1 { 3. [TestMethod] 4. public void Test_AddMethod() { 5. BasicMaths bm = new BasicMaths(); 6. double res = bm.Add(10, 10); 7. Assert.AreEqual(res, 20); 8. } 9. [TestMethod] 10. public void Test_SubstractMethod() { 11. BasicMaths bm = new BasicMaths(); 12. double res = bm.Substract(10, 10); 13. Assert.AreEqual(res, 0); 14. } 15. [TestMethod] 16. public void Test_DivideMethod() { 17. BasicMaths bm = new BasicMaths(); 18. double res = bm.divide(10, 5); 19. Assert.AreEqual(res, 2); 20. } 21. [TestMethod] 22. public void Test_MultiplyMethod() { 23. BasicMaths bm = new BasicMaths(); 24. double res = bm.Multiply(10, 10); 180 25. 26. 27. } Assert.AreEqual(res, 100); } We can see that in every test function, we use Microsoft Unit test framework for the managed code Assert.AreEqual method to verify that the ending balance is what we expect. To build and run the test. • • • Either go to Solution Explorer (Ctrl +Alt+L) and right click on Solution ‘BasicMath’ and click on Build Solution or go to Build Menu (Alt + B) and Click on Build Solution. Choose Test Menu -> Run -> All Test or instead of this step, you can follow the given step also. Go to Test Explorer and click Run All to run the tests for all the test methods . As the test is running, the status bar at the top of the Window is animated. At the end of the test run, the bar turns Green if all the test methods pass or Red, if any of the tests fail. You should now see something, as shown below. 181 In this case, If the test fails; the test method is moved to the Failed Tests. group. Select the method in Test Explorer to view the details at the bottom of the Window. Analyze your test results why it failed The test result have a detailed message which describes the reason why your test failed. For the AreEquals method, you can see a message which displays you what was actuallly expected (the (Expected<XXX>parameter) and what was actually received (the Actual<YYY> parameter). Correct the bug to make test pass To correct the error, simply replace +(Plus) with *(Multiply). 1. public double Multiply(double num1, double num2) { 2. return num1 * num2; 3. } Rerun Test to check if it is working or not In Test Explorer, choose Run All to rerun the test. The red/green bar turns green, and the test is moved to the Passed Tests group. 182 Cheers! We learned how to write a Unit test. TDD(Test Driven Development) Implementation using Unit Testing in C# As we discussed earlier in this article most developers follow the concept of write Test first then Code Later approach, we are going to learn TDD approach and to know how to use it. Test-driven development (TDD) is basically a specification technique and software development process that always depends on the repetition of short development cycles. In Test-driven development(TDD) software development process, first the developer writes an automated test case which is also called as initially failing test case that defines a desired improvement or new function, then writes the minimum amount of code to pass that test, and finally use the refactors concept in the new code to make it acceptable standards. 183 One of the advantages of using Test-driven development (TDD) is that it enables developers to take small steps while writing software programs. For example, assume you have added some new functional code in your running projects, and then compile, and then test it. There are high chances that your tests will be broken by defects that exist in the new code of your programs. With the help of TDD concept It is much easier for a developer to find and then fix those defects if you’ve written two new lines of code then two thousand lines of codes. It is generally prefered among programmers to add some few new lines of functional code before they recompile and rerun tests. The motto of Test-Driven Development is Red, Green, Refactor. • • • Red: Create a test and make it fail. Green: Make the test pass by any means necessary. Refactor: Change the code to remove duplication in your project and to improve the design while ensuring that all tests still pass. The Red/Green/Refactor cycle is repeated very quickly for each new unit of code. Let’s Implement TDD using MS Unit Testing Let’s take the exact same sample of code which we’ve used earlier in this article. We will create four basic functions like Add, Subtract, Multiply and Divide, which will need to be tested. In an earlier example, we have written the code first, then Unit Test later but as this is TDD implementation; we will write Unit Test first, then we will write the code later. To write Unit Test, follow the steps given in the image given below. • • • Create new project. Click on Test. Click on Unit Test Project Write Project name. Eg – BasicMathTDDTest followed by clicking OK button 184 You will get the default code template, as given below to write your test code. 1. using System; 2. using Microsoft.VisualStudio.TestTools.UnitTesting; 3. namespace BasicMathTDDTest { 4. [TestClass] 5. public class UnitTest1 { 6. [TestMethod] 7. public void Test_Method1() { 8. // TODO : Add test logic here 9. } 10. } 11. } Here, we are going to write test code first before writing the actual code, which needs to be tested. 185 The code will look, as shown below. 1. public class UnitTest1 { 2. [TestMethod] 3. public void Test_AddMethod() { 4. BasicMaths bm = new BasicMaths(); 5. double res = bm.Add(20.50, 20.50); 6. Assert.AreEqual(41, res); 7. } 8. [TestMethod] 9. public void Test_MultiplyMethod() { 10. BasicMaths bm = new BasicMaths(); 11. double res = bm.Multiply(10, 10); 12. Assert.AreEqual(100, res); 13. } 14. } As you can see that there are two test methods- Test_AddMethod and Test_MultiplyMethod and both the methods are using BasicMaths class, Add and Multiply method, which are not yet defined. When we run this Application, you will get an error, as given below. To make MS Unit Test run, we need to create BasicMaths class and add reference to Unit Test project. Follow the steps given below to know how to create BasicMaths class and add reference to MS Unit Test Project. • Right click on Solution ‘BasicMathTDDTest’. 186 • • Click ADD. Click New Project. It will open a Add New Project Window, where you have to follow the steps given below. • • • Click Visual C# (If you are writing code in C# language) Click Console Application. Write the name of the project. Here, the project name is BasicMath and click OK button 187 Now, write Add and Multiply Method under BasicMaths class for which we have already written MS Unit Test. The code will look, as shown below. 1. public class BasicMaths { 2. public double Add(double num1, double num2) { 3. return num1 + num2; 4. } 5. public double Multiply(double num1, double num2) { 6. return num1 + num2; 7. } After writing the code, you can see that there are 0 references of BasicMaths class as well as Add method function but these functions are already being used in MS Unit Test project. To make it accessible, we need to add this project to MS Unit Test Project reference. 188 Once you add reference, its time to run the Test. To run the Test, you can either go to Test -> Run -> All Test or move to Test Explorer and click Run All. After running Tests, you will see the output, as given below. Both Test Method Test_AddMethod and Test_MultiplyMethod failed. To know why these methods failed while testing, click each method and read the reason. In Test_AddMethod Assert.AreEqual is supposed to give 41 as an actual value but we are expecting 21. It must be 41 to get Test passed. Of course after adding 20.50 and 20.50, we will get 41. Thus, we have written the wrong expected value. Change it to 41 instead of 21. 189 In Test_MultiplyMethod Assert.AreEqual is supposed to give 20 but we are expecting 100. It must be 20 to get the test passed but logically after multiplying 10 and 10, we should get 100, then why its actual value is returning 20. Check the code of Multiply method in BasicMaths class. As we can see we are using +(Plus) operator between two operands- num1 and num2 which should be *(Multiply) operator. Now, the given code is a logically correct one. 1. public double Multiply(double num1, double num2) 2. { 3. return num1 * num2; 4. } 190 After correcting wrong values and codes, let's run the test again and see the result. Both Test methods Test_AddMethod and Test_MultiplyMethod are passed. Course Materials https://www.softwaretestinghelp.com/difference-between-test-plan-test-strategy-test-case-testscript-test-scenario-and-test-condition/ https://www.c-sharpcorner.com/article/a-basic-introduction-of-unit-test-for-beginners/ Activities and Assessments Using the application created in Module 5, create a Unit Test Project and implement testing scenarios for that application. Make sure to implement the following test results: • True Positive • True Negative • False Positive • False Negative 191 192