C# Learning
C# Learning
C# Learning
What is C#?
C# is pronounced "C-Sharp".
It is an object-oriented programming language created by Microsoft that runs on
the .NET Framework.
C# has roots from the C family, and the language is close to other popular languages
like C++ and Java.
The first version was released in year 2002. The latest version, C# 12, was released in
November 2023.
C# is used for:
C# is a programming language.
.Net is a framework for building applications on Windows
.Net framework is not limited to C-sharp.
There are different languages that can target .Net framework and build applications using that
framework.
Examples are C#, F# or VB .NET.
what is Dot Net Framework?
History of C-Sharp.
Before C# We had two languages in the C family the C language and C++
with either of these languages when we compile our application, the compiler translates our
code into the native code for the machine on which it was running.
Now we know we have different hardware and we have different operating systems like
Linux. So if I took an application that compiled the application on the computer with a
different architecture that would not run. So when Microsoft was designing the C-sharp
language on the .NET framework they came up with an idea, that they borrowed from the
Java community.
In Java the computer code is not translated directly into the machine code.
It's translated into an intermediate language called bytecode
So CLR it is essentially an application that is sitting in the memory whose job is to translate
the IL code into the machine code. And this process is called just in time compilation or JIT.
So with this architecture we can write an application in C-sharp and we don't have to worry
about compiling that into the native code for different machines. As long as a machine has
CLR that can run wer application.
.NET Architecture:
When we build an application with C-Sharp our application consists of building blocks called
classes
.
These classes collaborate with each other at runtime. And as a result the application provides
some functionality.
.
what is a class?
A class is a container that has some data which is also called attributes and functions which is
also called methods.
Think of a car a car has some attributes like its model its colour.
These are the attributes of a car.
An example of that is classes that are responsible for getting the data from the user process
the data and display something to the user.
Now as the number of classes in an application grows we need a way to organize these
classes.
That’s where we use a namespace.
So, a namespace is a container for related classes.
For example, in .NET framework we have name spaces each containing tens of related
classes.
We have name spaces for working with data like databases.
We also have name spaces for working with graphics and images.
We have name spaces for working with security
now in real world application as these name spaces grow, we need a different way of
partitioning an application and that’s where we use an assembly
So as we see in the list we can build desktop applications web applications apps for cloud,
services workflows and various kind of things.
So on the left side select Windows and on the right side select console application then give a
name to the project.
So let's call it hello world which is a common tradition when learning a new language and
specify a location.
I know this concept of solution in visual studio we have this concept of solution which can
have one or more projects with a very simple application.
We have only one solution and one project but as wer application grows we add more
projects each responsible for something different.
No we don't have to worry about it now click OK.
In fact, I personally hardly ever use solution explorer because I do everything with my
keyboard. And if we watch my course double wer coding speed we will see that everything is
possible with keyboard.
Now let's take a look at this first our program so we created a console application and on the
right side we see the solution explorer panel in case we don't see that go to view and select
solution explorer.
So at the top we see we have a solution which has only one project under that we've got the
project called Hello world.
Look at this four items here.
Properties expand that we have a file here called assembly info.
This is the identification for the assembly that will be produced as a result of compiling this
application.
So when we compile a console application we're going to get an executable. And that's an
assembly that assembly has an identification.
Look at these attributes here.
Like the title, description which is currently not set.
Company, product, copyright, trademark, culture a great we know various kind of things like
even version.
So these are all part of assembly identification or assembly manifest. In most cases we don't
have to worry about it, but if we want to create an assembly and we want to distribute it Send
to other people.
Then we may want to come here and give it a proper name and a proper version.
Under references We see any assemblies that this project is referencing to do its job.
When we create a project with visual studio by default it set a reference to a bunch of
assemblies that we see here, these are all part of Dot Net framework.
So at a minimum Visual Studio assumes we're going to use classes in System assembly or
System.Data to work with databases and so on.
We may not necessarily use all these assemblers in wer project but that's just part of the
template.
What is this all about. Well our project is called the hello world. So by default visual studio
creates a namespace called HelloWorld when we write code in this namespace, we have
access to any classes defined in this namespace.
So if we want to use a class that is defined in a different namespace we need to import it in
our code file. And that's why we use the using statement.
By default, we have a class called program so every console application we create with
Visual Studio has a class called program Inside program by default.
We have a method or a function called Main and that's the entry point to the application.
So when we run wer application C-L or executes the code inside main method and that's
where everything
kicks off this method is declared as static.
And that's something I'm going to cover later in the next section.
Methods have input and output.
So what goes inside parentheses the input to the method which we call parameter or
argument.
Know that parameters are optional.
But in this case the default template the main method has a parameter called args which is of
type String
Array.
We're going to learn about String Array in the next section.
What do we see before the method name is the return type or the output of the method void in
C Sharp
means nothing.
That means this method does not return any value.
It just contains some code that's it.
Also note that C sharp is a case sensitive language so this main has to be with capital M
otherwise
C-L R is not going to find this method as the entry point of the application.
Okay and one last thing is not this curly braces so we're half a block of code.
We need to surround it with curly braces so that is applicable for methods for classes and for
name
spaces.
Right now most write a very simple program.
So let's go here.
We have a class called Konsole which is used to read data from console or write data to it.
It has a bunch of methods we can access this Smethurst using the dot notation.
And here we see various members of this class.
Methods are indicated by a purple cube.So beep is used to play a beep sound.All clear is used
to clear the console.
We get to use the right line method.This method can optionally take a parameter.So I'm going
to pass a string here.
Hello world.
Just that I know that statements in C# terminate with a semicolon as we see here.
Now take a look at using system on the top.
Do we see that it's highlighted where as the others are greyed out.
The reason for that is in this file we are using a class called Konsole which is defined in the
system
namespace.
That's why that using statement is active.
We are not using any classes defined in other names spaces and that's why they're great out so
we can
get rid of them to make our code cleaner.
We can delete each one by control X like that.
Or if we're using resharpen we can't get rid of all of them by pressing alt and enter here and
selecting
the first option which is remove unused directives in file so it's faster.
Now let's run the application with control and F5.
So this we know that we see here this black window is what we call console and that's why
this kind
of project is called console application.
Summary:
C# vs .NET
CLR
A namespace is a container for related classes. So as our application grows in size, we may
want to group the related classes into various namespaces for better maintainability.
As the number of classes and namespaces even grow further, we may want to physically
separate related namespaces into separate assemblies. An assembly is a file (DLL or EXE)
that contains one or more namespaces and classes. An EXE file represents a program that can
be executed. A DLL is a file that includes code that can be re-used across different programs.
In the next section, we'll learn about basics of the C# language, including variables,
constants, type conversion and operators.
========================================================================
A variable is a name that we give to a storage location in memory where we can store a value
and it can stand in any immutable value that is a value that we know at compile time and that
value cannot change throughout the life of the application.
concept of overflowing.
We have declared a variable of type byte code number and assign it to 255.
As I told we earlier in the slide 255 is the largest value we can store in a byte.
Now in the next line I'm increasing the value of number by 1 and trying to store 256 in the
number.
But if we compile the application and display number on the console we'll see 0.
And this is what we call overflowing.
So we have exceeded the boundary of the byte data type in C-sharp by default.
We don't have overflow checking which means we can modify the value of a viable add
runtime and if we
go beyond the boundary of it's underlying data type we will get overflow.
Now sometimes this is not desirable in wer application.
We want to stop water flowing.
If that's the case we need to use the check Keyworth.
So here is how it works.
We have to check key word followed by curly braces which indicate the code block and
inside that block
we have the variable declaration and any kind of Earth mining operations with this code
overflow will
not happen at runtime.
Instead an exception will be thrown and the program will crash unless we handle the
exception.
The topic of exceptions is an advanced topic and I've covered it in my C# advanced course.
For now all I want we to know is that if we use the check keyword overflow a lot happen and
instead
the program will throw an exception.
Now do we really need that in reality.
Honestly I have never ever ever came across this situation.
Because if I was concerned that in this case my number variable would overflow.
I would just simply use the short data type instead of byte but I decided to include the concept
of
overflowing because I wanted my C Sharp course to be comprehensive So just be aware of
that.
In case we hear about overflowing summer but we're probably not going to use that in the
real world
in the next lecture we're going to talk about the concept of scope
scope:
If I go out of this block and try to access a the program will not compile the same rule applies
to
other variables.
So let's take a look at this block here.
B is meaningful anywhere inside this block or any of his children.
If I go outside this block and try to access B I'm going to get a compile time error.
So in order to use the console class we need that declaration here on the top.
If we're not using resharpen we have to go here and manually type using System semicolon.
OK now take a look at this number here.
It has a red underline.
And if we put the mouse cursor here it says local variable number might not be initialized
before accessing
.
If we remember from the slides I told we in C-sharp before we can access a variable we need
to set
it in it to initialize it.
And that's the reason here we have the red underline we cannot display the number on the
console before
initializing that.
So if I try to compile the application we're going to get an error to compile an application we
press
control shift and B.
And here's the aerialist use of unassigned local variable number.
We can solve this problem by initialising number like setting it to 2 for example.
And we see the red underline is gone.
We can compile again.
Control shift B will succeed.
Take a look here.
OK.
Now we can run the application by press and control and F 5.
OK.
So we got two on the console.
Now let us extend this example and declare a few more variables can define an integer int
count equals 10 and a float float.
So a total price equals twenty ninety five dollars.
Now note this red underline here.
Let's find out what's happening here.
So I put the mouse cursor here.
It says cannot convert.
Source type double to target type float.
If we remember from the slides I told we by default the seashore compiler traits real numbers
like
this one here as double where as we are declaring a float.
So here we need to explicitly tell the compiler to treat this real number as a float and we can
do that
by appending an F at the end.
So the error is gone.
Mystic inner character char character A calls a.
No that is are we enclose characters by a single quote like here.
We can also declare a string string is not one of the primitive types and I have covered it in a
separate
lecture in this course.
But for now let me show we how to declare a string which just type string.
Give it a name first name a cause Marsh know that with strings being close them in double
code.
So that's one of the differences between strings and characters.
And finally let's declare a bull.
Bull is working a course.
True.
So with boules we can either set them to True or false both true and false are Keyworth as we
can see
they're indicated by the blue color here and they're lowercase.
So everything we see here that is blue is a keyword like a static void string class namespace
and all
these data types here nounless display these variables on the console.
So let me show we a trick.
Instead of writing cancel the write line.
We can do a shortcut.
This is what we call a code snippet.
So we type the CW that is short for console right line and then press tab and visual studio
automatically
converts that to cancel the right line.
There are various code snippets that help we write code faster and I will try to point them out
throughout
this course.
So let's just play count.
Now another one.
Total price.
Not that I can't just type T.L. And here's what we call intellisense is Visual Studio.
Auto completion mechanism.
We don't have to type the full name of a type or a variable as long as the intellisense detects
that
and is highlighted here like total price.
We can simply press tab and there we go.
Visual studio automatically completes that for us.
Let's display the character.
Same here.
I just press tab again.
I typed only a few characters that can press tab or enter.
And finally is working.
We run the application by control at 5.
So we got all these values on the console
OK now let me show we something else in C-sharp.
We have a keyword called vore which makes variable declarations easier.
For example here instead of explicitly specifying the data type for each of these here I can
simply
type var and I let the C-sharp compiler detect that data type for this variable here.
So let me replace all of this with var.
OK now if we hover the mouse over the word key word we can see the underlying data type.
And in this case it is system that boolean which is the dominant type which maps to C-Sharp
bool keyword
.
I with this one that's a string.
And this one is a character and this one is system that single which maps to float in.
And in the case of count it's in 32 which is integer and same for number.
So the tricky thing here is by default C-Sharp creates integral numbers as integer.
And when we use the VAR key word it assumes that it's an integer.
If we really want to go for a byte then we have to explicitly say mystified as byte here but tell
we from experience it's safe to use integer.
In most cases in fact if we look at the classes in the .NET framework in most cases integer is
the data type used for representing integral numbers.
OK I reverted back.
So it's a char which is a character we can put the mouse cursor here and press control and
then click that opens the object browser window.
Take a look here is Object Browser and it's a way to look at the various classes in wer project
or in the top that framework.
In this case because I did a control click on the char or var keyword.
This is what we got here.
So char is highlighted in the ogic browser on the right side we see all the members of the char
type
.
So these purple ones are functions or methods.
If we scroll down here we'll see two fields here main Valeo and max value.
We'll explore them shortly and note that here is the declaration of char char is a structure we
will
cover as structures later in this course.
And note that it's a member of System namespace.
We can click system and that shows the System namespace as well as all the types defined in
the System
namespace.
So these are part of the dominant framework.
OK let's close this for now.
Let's explore another example.
So I'm going to get rid of all the code here we because simply press control X on each line
and that deletes all these lines here.
OK let's do it.
Cancel the write line.
So CW tab this time I pass a string here and we specify two placeholders
and finally supply a couple of arguments.
OK let's see what's going on here.
So here what we have is called a format string.
It's a kind of string that can be used as some kind of template.
So at runtime what we have here indicated by curly braces and zero as the argument will be
replaced
by the value we pass here.
So 0 represents the first argument after this format string and one represents the second
argument after
this format string in this case byte the next value.
So let's run this application.
We got 0 and 255 and that's the range that we can store in a byte.
We can do the same with the float.
So CW tap a format string
float mean value float max value.
Run the application.
So this is the range we can store with a float.
It's a huge number that is displayed using the scientific notation
.
OK now let's take a look at constants.
So I get rid of these two lines here.
Control X control X we define a constant with the const keyword Konst float P three point 1
4 and we
have to put f at the end because it's a float.
Now because we declared p as a constant here I can change it in my program so I can go here
and say
P it cools one.
The compiler is not happy and that's why we see that red underline here.
If we hover the mouse here it says read only local content cannot be used as an assignment
target.
It's a little weird expression to understand but basically the intention of using constants is to
have
some kind of safety in wer program.
So if there are values that should not be changed beyond wer program we defined them as
constants
.
And this way we won't accidentally modify their values
And this video I'm going to talk about various kinds of type conversion in Souchong we have
implicit
type conversion explicit type conversion which is also called casting and we also have
conversion between
non-compatible types.
Here is an example of implicit type conversion.
A bite as we know takes only one bite of memory and an integer takes four bytes.
So we can easily copy a byte to an integer.
What happens at runtime is let's take a look at this slide.
So here is the binary representation of our b variable here.
So one is represented as seven bits of 0 and 1 bit of one.
When we copy a by to an integer what the runtime does is it prefixes that value with a bunch
of zeros
to fill the four bytes.
So there is no data loss.
In situations like that when the compiler is 100 percent sure that the types are compatible and
no data
loss will happen.
Values can be converted to a different type implicitly.
Here's another example of implicit type conversion.
So we have an integer set to 1 and we copy that to a float.
Again in this example no data loss will happen.
Well let's take a look at this one.
Here we have declared an integer and we are trying to copy that to a byte and integer is four
bytes
.
So when we convert that to a byte three bytes out of four bytes will be gone and there is a
chance for
data loss.
Now data lost doesn't always happen.
It only happens if the value will be stored in the integer is beyond the capacity of a byte.
In this example one can be stored in a byte so no data loss will happen.
But if we had let's say 300 here we cannot store 300 in a byte.
So as a result of that conversion they told we lost when the compiler knows that there is a
chance for
data loss.
It doesn't allow implicit type conversion and we need to explicitly tell the compiler that we're
aware
of the data loss and we still want to go ahead with the conversion.
In situations like that what we do is we prefix that variable with the target type.
So here I'm trying to convert I to a byte.
This is what we call as casting.
Here's another example.
So we have a float set to 1.0.
And if we try to convert that to an integer the compiler would complain.
I was sure that later in the coding demo.
So we need to tell the compiler that we are aware of the data loss and we still want to convert
F which
is a float to an integer.
So we cast it like here.
Sometimes we are working with types that are not compatible but we still need to convert
them.
For example we might have a number represented as a string as we see here and we need to
convert it
to an integer.
In situations like that because string and end are not compatible we cannot use explicit
casting.
So we need a different mechanism for converting a string to a number.
In situations like that we need to use the convert class or use the Parse method to convert
classes
part of data framework and it's defined in the system namespace.
It has a bunch of methods for converting various types to other types and they all start with
two.
In this case we're trying to convert as much as a string to an int 32 and 32.
As we know is a dot Net Framework type which maps to a C-sharp integer type.
Remember a byte is one byte as short is two bytes and integer is four byte long is eight bytes.
We probably know that each byte has eight bits.
So an integer which has 4 bytes times eight beats ends up being 32 bits.
That's why it's called two in 32 and in 16 which represents 16 bits equals two short which is
two bytes
.
We also have this parse method here all the primitive types that I explained in the last lecture
like
integer long float boolean.
They all have this parse method and the Parse method takes a string and tries to convert that
to the
target type.
In this case an integer.
Here are some of the methods that we can find in the convert class to byte which converts the
given
value to a byte to in 16 to convert the given value to a short to in 32 to convert the given
value to
an integer and 2 in 64 to convert the given value too long.
OK enough theory.
Let's jump into code and see all this concept in action.
Okay let's say implicit type conversion in action first I declare a byte.
Call it B.
Answer that one.
And I declare an integer and set it to be.
Again to recap a byte is only one byte and an integer is four bytes.
So we can copy me to I without data loss and as we see there is no compile time error here.
Let's put the eye on the console so cancel that right line and we pass on here.
Note that as I typed console the right line.
My resharpen plug in automatically.
I did this using System statement on the top again.
If we don't have the sharper We need to go manually add this statement here we run the
application
by control on F5.
So we got on the console.
Now let's reverse this and see what happens.
So I'm going to get rid of this code here.
Control X control X control x.
First I declare an integer.
Set it to 1 then declare a byte and try to copy I to be.
We immediately got this red underline here.
If we hover the mouse here that tooltip says cannot convert source type into the target type
bytes
.
Sometimes this error might be in a different file which is not open in visual studio here.
So we may see the error when compiling the application.
Let's simulate that.
So I compile this application by Control shift and B which stands for build.
So here is the error cannot implicitly convert type into two byte an explicit conversion exists.
Are we missing a cast.
So now we understand the concept of implicit versus explicit type conversion.
So what we need to do here is to do a cast.
So we cast an integer to a bite.
In this case no data loss will happen because the value is small enough to be stored in one
byte.
Let's put me on the console console the right line be run the application.
So everything is good.
But let's see what happens if we said I to let's say thousand we cannot store the number of
thousand
in a byte.
The maximum we can store in a byte is 255.
So if we run the application now we got to 32 because some of the bits were lost and this is
the reason
that C-Sharp compiler knows that there is a chance for data loss and it forces we to explicitly
specify
the cast.
Sometimes we know that despite the differences in data types there is no chance of data loss
like in
the last example where I was set to 1.
In those cases we can safely apply a cast.
OK let's take a look at non-compatible types.
So let's clean up this code.
I start by declaring a string is called a number and set it to 1 2 3 4.
Just recapping from The Last Lecture note that here I could declare these with the very key
words and
C# compiler automatically detects that this is a string.
So a number will be defined as a string.
And we can see that by hovering the mouse here it says system that string.
Now let's say we want to convert that to a number.
If I declare an integer like I I cannot cast that number to an integer because they're not
compatible
.
Let's take a look at the error cannot cast expression of type string to type int.
So if we see that error that's the time when we need to use the converse class.
So we type in convert dot.
Take a look at this method to here to bite to char to in 16 in 32 and many other methods here.
So let's convert that to an integer which is 32 and past number as an argument here.
Now let's print out the eye on the con.
.
Run the application.
So it is one two three four.
All good.
But let's see what happens if instead I declared this as a byte.
And here we need to use convert dot to bite.
And here with display being on the console a byte does not have enough storage to store the
value of
1234.
So when we run the application now
application crashed we can sell this here.
And here's the exception exception is Dartmouth's frameworks error reporting mechanism.
It's an advanced topic and have covered it in detail in my C-Sharp advanced course.
But in this video I will briefly show we how to handle exceptions.
So here it says unhandled exception the type of exception is system the overflow exception
which means
we try to store a value that goes too large or too small for a byte.
So each exception or error as a type in this case the overflow exception and has a message
value was
either too large or too small for an unsigned byte.
Sometimes the exception messages are friendly enough that are easy to understand.
Sometimes they're a little bit tricky.
And the best way to work out what is going wrong is to jump on Google and search for the
error.
And there's pretty much always a stack overflow page that explains that.
Now let's discard that.
Let's see how to handle the exception here.
So the exception happened during conversion of that string to bite what we need to do here is
to wrap
these few statements with a try catch block.
Let's see how it works.
So I just typed try and press the enter and visual studio automatically generated this block for
me
.
Again this is what we call a code snippet.
Let me do this I show we one more time.
So try a serious try here and they Intellisense and this icon represents a code snippet.
So if I press enter or tab we automatically get this code block.
So what I'm going to do now is to move this code into a try block and the catch block gets an
exception
by default visual studio as this throw here.
Don't worry about it just delete it again.
I will explain it in detail in my C-Sharp advanced course.
For now let's see what's going on here.
So the code that we put inside the try block will be somehow monitored and if an exception
happens
this block will be executed.
This prevents wer application from crashing.
The reason our application crashed earlier was because we did not handle the exception.
So if we don't handle exception the exception will be propagated to the Dartmouth runtime
and the runtime
mechanism is to stop wer application and display the error.
Here we can handle the exception and that would prevent exception from being propagated to
the runtime
.
So instead we can display a friendly message to the user saying for example console that right
line
.
The number could not be converted to a byte.
Now let's run the application again.
See we got that friendly message and application didn't crash.
So what I want we to take away from this lecture is this Convery class.
Works pretty well in most cases but in cases where the source type cannot be converted to the
target
type there is a chance for exception.
And we need to be aware of that and what we need to do is to wrap this block of code with
try catch
.
Let's take a look at one more example before we finish this lecture.
Let's remove this and instead define a string.
Call it as we are and set it to true.
We can use the converse class to convert that value to a boolean so it will be a Cool's convert
that
to boolean.
And we passed that SDR.
Here again in this example the string and bool are not compatible and that's why we cannot
use explicit
casting.
So here we are using the converse class.
Can display be on the console.
Let's run the application.
So the truth string was successfully converted to a boolean value.
OK that's pretty much it for this lecture.
Before I finish I just need to emphasize something here that throughout this course during
early lectures
we may see me using some short variable names like B or SD are here.
That's purely for demonstration and keeping things simple and in building real world
applications.
We should really avoid naming our variables a b c SDR.
It's not really a good practice.
The only exception is when we get two loops which we will see later in this course in four
loops.
We use counter variables and we call them I or J.
It's a common convention.
Now here we are just starting to learn C-Sharp and it's really impossible for me to
demonstrate building
a real world application because we're just covering the basics or alphabets.
I hope we enjoyed this lecture and thank we for watching
C# is aesthetically type language which means once we declare a viable we need to specify
this type and that type cannot change during the lifetime of that variable.
SECTION 4:
Earlier in this course we'll learn that classes are building blocks of our applications.
These classes combine related variables or fields and functions together.
So here's an example.
In this picture we have a class called person with four fields name age height and weight.
And it also has four methods or four functions.
Walk talk eat and sleep.
This class is a type or a blueprint from which we create objects.
So an object is an instance of a class.
In this example we can create three instances of this person class like John Murray and Scott.
So more accurately when we run wer application it's these objects that are talking to each
other and
collaborating to provide some functionality.
But the world class and objects are often used interchangeably.
OK now let's see how we can create a class in C-sharp.
So to create a class we start with an access modifier and then the class keyword and an
identifier an
access modifier determines who can access this class.
For now don't worry about it because that's something I have covered in my C-Sharp
intermediate course
which is the second part of this course.
Just remember whenever we want to create a class use the public keyword to make the class
accessible
anywhere in wer application.
Inside the code block class we can have variables which we call fields.
Also note that when we declare a variable we need to specify an access modifier.
Again for all examples in this course.
We're going to stick to public and in the next course we'll take a look at other access
modifiers.
Note that in C-sharp anywhere we have a statement like a variable declaration here.
We need to terminate that statement with a semi-colon but we don't have to do that when we
have a
code block.
Wer classes can also contain methods.
So here is an example.
In this example void is the return type or to introduce method which means this method does
not return
any values.
And also note that this method does not take any promotors as indicated by empty parenthesis
so it simply
outputs the name of the person on the console.
Here's another example.
In this example we have a calculator class with one method which takes two parameters of
type integer
and returns an integer.
Now that we have a class let's see how we can create an object.
So earlier we learn that to declare a variable we start with a type and then an identifier
creating
objects or instances of classes is pretty similar.
We start with a type and an identifier.
But there is one more step we need to allocate memory for that object and that's when we use
the new
operator.
So in C-sharp classes are treated differently than primitive types.
So we need to explicitly allocate memory for them.
But the good thing is unlike languages like Objective C or C++ we do not have to worry
about the allocating
that memory.
C-L are our Common Language Runtime will take care of that for we.
It has a process called garbage collection which automatically removes all objects that are not
used
.
So to allocate memory to an object use the new operator and then repeat the type of the class
and practices
.
We can make this code a bit shorter by using the Varg keyword that we learned earlier and
now that
we have a Person object we can access its members like named field or the introduced
method using the
dot notation.
So in this example I set the name of this person and then call the introduced method.
Now let's see what is not static modifier that we saw in our first C-Sharp program.
So here's the calculator class that we saw earlier.
We can modify this method with the static keyword like this and as a result we can access
that method
directly by the calculator class itself.
We do not have to create an object to access a static member.
In fact we cannot access static members from objects.
So what is this all about.
Why do we need this.
Well let me show we what's happening behind the scene and then we will have a better
understanding
of this.
So without the static modifier when we create three objects of this calculator class each
object in
the memory will have the add method.
But when we apply the static modifier the add method will be only in one place in memory
and that is
the calculator class itself.
So it's not going to be repeated three times in memory.
By the way do we need this.
We use the static modifier when we want to present a concept that only a single instance of
that should
exist in memory.
Here's an example.
Remember the Program class in our first program.
So there we had a main method and Main was modified with the static keyword which means
there is only
one instance of the main method in memory.
There is only one entry point in each C-Sharp application.
Current day time is another example.
We don't want to have multiple date time objects in memory each representing a current date
time.
We want only one place in memory where we can look at the current data.
So all I want we to know for now is that when we modify any members of a class whether it's
a field
or a method with a static modifier that member will be accessible from the class itself not an
object
.
Well that's we know three for now.
Let's flip over to Visual Studio and do some coding
OK here I have a blank console application and I want to create a class called person so we
can create
a class here inside the main method because that's a function or a method.
So we need to create a class at the namespace level.
So look here we have a namespace and here's one default class.
We can create another class at this level.
So public class person code block.
Now listicle are a couple of fields so public string first name public string last name I as
declare
a method Pawlick void which means it doesn't return any values introduce.
And here I simply use console the right line to output the full name of this person on the
console console
.
Dot writes line.
My name is first name plus I would like to add a space between them and last name.
Nounless create an object of type person.
So we go to the main method.
We can start with person let's call this John equals new person I know the green highlight
here resharpen
is suggesting to use var to make this code a bit shorter and cleaner.
So I put the cursor here Altan enter and enter.
Now let's set the first name and last name for this object.
So John dot first name he calls John John that last name.
He calls Smith.
I know we can call the Introduce method.
Let's run the application control and F5.
So my name is John Smith.
OK now let me show we something.
When we write a real world application we're going to have tens hundreds or even thousands
of classes
.
So we're not going to put all of these classes inside this file here.
Otherwise the file will explode.
So we want to have one class profile.
If we have the sharper We can easily move this class to a new file.
So all we do is put the cursor on the class name press Hultin enter and not the first option.
Move to person that see us enter.
What happened was resharpen automatically created a new file called person that's yes and
move this
class from program that c file which was here inside the new file.
So I didn't have to go manually create a new file and type the name of the cluster but if we
don't
have sharper it is perfectly fine.
So to add a new cluster of project go to solution explorer right click on wer project then go to
add
.
Actually we can see that here let me drive the solution explorer to the left.
OK.
Right click on that class or we can use the shortcut shift.
And see.
Now I just don't have to type the name of wer class let's say calculator.
That's it.
Now we got a new file here calculator.
Yes.
And here's a class.
Note that in this example because the name of my project is C-Sharp fundamentals.
Every time I create a class by default it's either inside the seashore fundamentals namespace
and the
introduction of this course.
I explain that we want a group related classes inside different name spaces so perhaps the cost
of the
person is different from calculator calculator is more about math.
Whereis person could be part of a commerce application.
So a better way is to Right-Click the project go to add new folder.
We create a new folder like math.
Then we moved this calculator cluster confirm.
The only problem is when we move the namespace is not changed by default.
So we need to go here manually and Daut math here.
Or if we have resharpening we don't have to even type that.
We can put the cursor on the name space and press alternate enter and enter.
And that automatically updates namespace the C-sharp fundamentals that math.
So here's our calculator class.
First we add the public key word so that it's accessible.
No that if I don't I die and I go to program that C-s I'm not going to be able to create a new
instance
of calculator.
So if I type calculator calculator the intellisense cannot find that class because it's not
accessible
.
Now we go to the calculator at the public key word here.
Back to the program
and resharpen is suggesting to import that calculator class which means adding a using
statement on
top of this file.
So with resharpen I can press Altan enter and I would automatically add this using statement
here.
But if we don't have sharper We have to go on top of the file manually type the name of the
namespace
where that class is declared.
So using C-Sharp fundamentals that math.
So we see resharpen makes coding a lot easier.
We're going to have to worry about these name spaces.
What class is in what namespace.
And we don't have to type them we just type the name of wer class and Lady sharper.
Do all the plumbing for we.
OK.
Now we have a calculator class let's create an object
and we use the new operator to allocate memory to that object.
And I just realized that we didn't have any method to this class.
So let's get back there.
Let's create a new method called that which returns an integer and takes two prime emitters a
and b
.
And it simply adds them together and returns them.
Now we save the file with control and as get back to program a quick way of doing that is we
press
control and tap and we can switch between the open windows in Visual Studio.
So we don't have to grab the mouse every time and click these tabs on the top.
We can do everything with wer keyboard.
So back to program.
Yes.
And here we call the ad method.
We pass two arguments one and two.
We can store the results in another variable var result = and we can output that variable on the
console
console.
That great line result.
Now let's run the application with control and F5.
So the result is three.
Now before we finish this lecture I want to show we something interesting here.
Look every time we use console died right line we access that method directly on the console
class itself
.
What does this mean.
That means the right line method is defined as the static.
We don't have to go and create a new console object in order to call the right line method.
So we all use a static modifier before without being aware of that.
In this case all method of the console class are declared as study because we only have one
console
when we run the application.
That's it for this lecture.
I hope we enjoy it.
And thank we for watching
In C-sharp we also have another type similar to classes which is called structure or struct.
So in terms of syntax it's very similar to a class.
The only difference is in sort of using the class keyword we use the struct keyword.
So similar to classes structures combine related fields and methods together.
But what is the difference if I read the C-sharp documentation.
We're going to see lots of tiny differences between classes and structures and we're probably
going
to be even more confused than when we started.
I personally don't find these subtle differences very pragmatic.
In fact in the real world 99 percent of the time we will create new types using classes not
structures
.
The pragmatic guideline I give we in this lecture is use structure when we want to define a
small
lightweight object like this.
RG recolor here or if we're dealing with something like a point that has an X and a Y we can
certainly
define that using a class.
There is no problem at all.
But if we're in a situation when we want to create thousands or tens of thousands of objects of
that
type it's more efficient to define them as a structure.
If not don't worry about it.
Just stick to classes because that's what we use most of the time.
Another non-permissive type we have in C-sharp is array and this lecture I'm going to give
we a brief
introduction of our age to get we started.
Later new scores course we have a separate section about arrays and there I will cover more
details
.
So what I'm covering this lecture is what is an array.
How to declare and initialize arrays and how to access array elements.
So what is an array an array as a data structure that we use to store a collection of variables of
the
same type.
For example imagine we would like to work with three numbers.
So instead of declaring three integer variables like number one two three we can declare an
array and
call it numbers.
No the square brackets here.
The first one is used to tell the compiler that we would like to declare an array.
And the second one is used to set the size of mothery.
So in C Sharp arrays have a fixed size which means we need to specify during declaration
and it can
not be changed.
Also note the new operator here.
When declaring an array we need to allocate memory for it.
And that's why we need to use the new operator also.
An array isn't an object behind the scene.
So in short we have a class called array.
And when we declare an array using this syntax here internally the compiler creates an
instance of
that class.
So an object.
And that's why we need to allocate memory for it.
Now that we have an array we can access its elements using an index that we supply in the
square brackets
.
Nobody in C-sharp arrays are zero indexed which means the first element of an array has the
index of
0 if we know ahead of time the values we would like to store in an array we can use the
object initialization
syntax and make this code shorter.
So during the declaration we supply the values in curly braces again.
This was a quick introduction to arrays so we can get started quickly and write some simple
programs
.
I'm going to cover arrays in more detail in a later section in this course.
Now let's flip over to Visual Studio and do some coding
OK in this video we're going to take a look at how to declare and initialize an array in C#.
So let's say we would like to create an array of integers.
So we started with and we used the square brackets to indicate that we would like to create an
array
not just an integer.
We give it an identifier or a name.
I know we need to allocate memory to it.
So we use the new operator and repeat into array again.
By this I would need to specify the size of the array.
So let's say three.
Now we can make this code a bit shorter by getting rid of this entire array here and just using
var
.
The compiler knows that number is assigned to an integer array as we see here.
So there's no need to repeat that twice.
Now I'm going to set the first element of this array and because in C-sharp arrays are zero
indexed
the first element starts with index of 0.
So numbers of 0 because 1.
Now let me show we something.
I'm going to display all the elements in disarray on the console so kaso the right line numbers
of 0
and I'm going to duplicate this line a couple of times with Control D which is one of
resharpen shortcuts
and I change the index on each line.
So this is a very basic way of displaying elements in an array and more efficient ways to use
a loop
.
And that's something we're going to look at in the next section.
Now let's run this application and see what happens.
So our array has three elements and the first one is initialized to 1.
But what about the others now that they are initialized to zero by default.
So that means when we declare an array all the elements are set to the default value of the
data type
for that array.
In this case because our array is of type Integer the default value for integers or any kind of
numbers
in C-sharp is zero.
If we had an array of booleans all elements in that array would be initialized to false.
Let's try that.
So I'm going to create another array.
Let's call it flags.
And this time I'm going to use a bully array.
Again the same size again Similarly I said the first element of flags of zero holds true and
only display
all elements in disarray.
Let's run the application.
So note that the first element of the boolean array is set to true.
But the second and third elements are false.
Now one more example.
Before we finished this lecture this time I'm going to create an array of strings and I'm going
to use
the object initialization syntax to initialize it during declaration.
So I'm going to call it names new string array of size 3 and I'm going to store three names
here.
So Jack John and Mary.
So with the object initialization syntax we start with curly braces and it's supply values for
each
element of the array.
That's pretty much it for this lecture.
Later in this course we're going to have a full section on arrays and there I'm going to convert
arrays
in more detail.
I hope we enjoy this lecture and thank we for watching
OK in this video we're going to have a quick introduction to strings so we can quickly get
started
.
And later in the course we have a separate section where we cover more details about strings.
So in this lecture I'm going to cover what is a string.
Different ways to create strings and sure.
And finally I'm going to talk about escape characters and verbatim strings which are pretty
handy.
So if string is a sequence of characters and as we can see in this example in C-sharp which
surround
strings with double quote as opposed to characters which are surrounded by single quotes
there are different
ways to create strings and share a very common way is to use a string literal.
So just like declaring a viable we started with a type.
And in this case string then an identifier.
And finally we assign it to a string literal.
We can also concatenate strings using the plus operator.
So in this example I'm adding first name plus a string literal which represents an empty
character.
And finally the last name.
Sometimes using string concatenation this way can create a bit of noise in wer code.
We might have different string variables that we're concatenating and it's hard to visualize
what
the output looks like.
If that's the case we can use string format.
So in C-sharp this drinky word maps to the String class in the Dot Net Framework and we
learn that
classes can have fields and methods and we can declare these members as the static which
means we can
access them directly on the class without the need to create an object.
So in the example we see here recalling the formatting method on the string class format is a
static
method.
So we can directly access it using string dot format.
This method takes a couple of parameters.
The first one is a format string which we use to define a template for a string inside this
template
.
We have placeholders placeholders are indicated by curly braces and they're Ziering next.
So here placeholders zero will be replaced by first name and placeholder one will be replaced
by last
thing.
So as we see in this example it's much easier to visualize the output as opposed to
concatenating multiple
strings together.
Sometimes we might have an array of objects.
We can create a string from combining all elements of that array using a separator.
So in this example we have an integer array with values 1 2 3.
And in the second line we are calling the join method of the String class which is a static
method and
we supply two arguments.
The first argument which is a string is a separator.
In this case I would like to combine the three numbers using a coma.
The second argument to this method is the array whose elements we would like to combine.
Now that we have a string we can access each of its individual characters using an index.
So in this case name of zero represents the first character in our string.
One thing we need to know about strings and C-Sharp is that strings are immutable which
means once
we create them we cannot change them.
So back to our example here we can certainly read the value of the first character in our string
but
we cannot change it.
So the third line here which is indicated by read is not going to be compiled.
There are methods in the String class that allows us to manipulate strings and modify their
values.
But all these methods return a new string so the original string is not changed and that's what
they
mean by immutable.
There are a few special characters in C sure that sometimes have different meanings.
For example if we want to have a new line in wer string we need to use backslash then when
the compiler
sees that it automatically as a new line if we don't add the backslash the compiler sees it and
just
as the letter N same for tap if we want to have a type we use backslash T.
Now that brings us to an interesting situation.
What if we want to use the backslash letter itself because when the compiler sees backslash it
thinks
we are using a special character so it's not quite sure.
It might get confused.
So if we want to tell the compiler that do like to use the backslash letter we need to represent
that
byte double backslash same for a single quotation mark and double quotation marks.
We need to prefix them with a backslash.
And that's what we call by as scaping characters in C-sharp.
But these are special characters.
The list of special characters in fact is even more than that.
But personally I have not found any of those special characters that we find in search of
documentation
.
Pragmatic those we see in this table are the ones I have found very common.
OK now because of these special characters there are cases where creating a string can be a
little bit
messy.
For example look at this path variable here know that all these double backslashes we have it
looks
a little bit messy doesn't it.
The good thing is in short we have a kind of string which we call verbatim string and with a
verbatim
string we don't have to use all these double backslashes we can simply prefix our string at
sign and
as a result we can get rid of all this double backslashes and just use a single backslash.
OK.
Now just flip over to Visual Studio and do some coding
OK let me start by creating a string called first name so string first name because mush.
Now obviously here we can use the Varn key word because compiler knows we have
assigned this valuable
to a string literal so that should be of type string so we can make the code shorter.
So I put the cursor here.
I can manually change that to var or would be sharper Altan enter and enter.
Now let me show we something interesting here.
Cover wer mouse over the marquee worth.
Note that this fireball is of type string which is a class that is defined in the System
namespace in
the lecture about primitive types.
I explained that all primitive types in C-sharp map to type in the Dot Net framework.
For example let's use that end and declare a variable like number.
If we have wer mouse on end we see that's of type in 32.
I know that this in 13:2 is the structure.
So all these keyboards we use in C-sharp like ain't char string float bulled they're all mapped
to a
type in the dot net framework the primitive types are all structures like this and or in 32 but
the
strings are classes.
So let me remove this.
Look at this one more time.
So we have a class in the System namespace which is called string.
What this means is we can create a string like this using the string keyword in C-sharp or we
can
use the string class in the Dot Net Framework.
The difference is when we use this string class we need to import that namespace.
The System namespace on the tongue.
Because here we are writing code inside this namespace but we are accessing a class that is in
a different
namespace System namespace.
So if we have resharpened we can automatically import that.
Otherwise we have to go on top of the file and type using system and call it.
So whether we use the string class like this example or using the string keyword
it's exactly the same.
There is no difference.
And that's one of the things that confuses beginners too C-sharp.
Similarly we can create an in 32 using the int32 structure in data framework.
Call it I or we can use int keyword.
They're essentially the same thing.
OK now let's clean up all the extra noise here and get back to our example.
I'm going to change just two var to make the code cleaner.
So one way to create a string is to use concatenation.
So we can declare another string and concatenate three strings together.
But as I explained sometimes it's hard to visualize the output and we can use the string format
method
.
So here is an example.
So string again maps to a system that string class and this class has a bunch of static methods
as we
can see here.
So these methods are accessible without the need to create an object they're accessible
directly on
the string class.
For example we can use the Compare method to comparing strings.
In this case we're going to use the format method.
So this method takes two arguments.
The first one is a format string or a template something like this.
And the other arguments are values to apply to this template.
So I'm going to pass first name and last name at runtime.
What we have here will be replaced by first name.
Same what we have in here will be replaced by last thing.
Now let's take a look at string that join.
So I'm going to create an array of names
and I'm going to create a string by combining all these values using a comma as a separator.
So
we use the join method again a static method on the string class.
The first argument is a string which represents a separator.
We can use coma.
And the second argument is the array.
So names let's display the result on the console.
So formatted names just like that.
So we see John come on Jack.
Come on Mary.
This is a very useful technique when we have some values and we will like to combine them
together
using a separator.
Now let's take a look at verbatim strings.
So I'm going to create a string that has multiple lines and has a few paths.
So something like this
.
This string is very unreadable.
So we see the output first.
And then I'm going to show we how we can clean this up using a verbatim string.
So instead of displaying formatted names I'm going to display the text year
.
So this is the output.
Hi John.
Then on a new line look into the falling pants then on to new lines.
We have two paths here.
As we see using a normal string is very hard to format something like that.
So we can use a verbatim string.
All we do is we prefix it with and that's fine then we don't need backslash n we can simply
put down
on a new line.
Same here.
Remove the max Leshin on a new line and we can remove all these double backslashes
.
So we see it's much easier to read and understand history.
So whenever we need to use backslash newline or tab use a verbatim string to properly
formatted string
.
So that was a quick introduction to strings to get we started later in this course.
We have a separate section where I cover more details about working with strings.
I hope we enjoyed this lecture and thank we for watching.
OK and other types are going to cover and the section is enums.
An enum is a data type that represents a set of name value pairs or constants.
Let me show we where we use nums in the real world.
Imagine we're building an application for a Post Company and we want to support a few
different shipping
methods.
So one way is to declare a few constants each representing a shipping method.
And in wer application based on the shipping method we can make decisions to calculate the
shipping
costs or the tax or display different messages to the user.
So the possibilities are endless Now even though this approach works it's a little bit messy.
It's better to define a new type where we can represent different shipping methods.
So that's where we use an enim so we can create a new enum called shipping method with
these three members
.
So in simple words use enums where we have a number of related constants and sort of
declare multiple
constants declare an ino.
This will be a new type in wer application just like we have classes or structures.
OK now that we have any we know we can use it with the dot notation.
Now one thing I wanted to know here is that an ether is internally an integer but if we have a
reason
to change that and use a byte instead perhaps it could be easier for we to map in wer database
columns
then we can specify byte during declaration of wer name.
So that's the basic idea.
But now let's flip it over to Visual Studio and let's see how to work with gnomes and how to
convert
them to numbers and strings.
Okay now I'm going to create a new noom called shipping method.
Note that because enim is a new type we need to define it at the namespace level.
So
now if we don't set any values to the members of this new the first member is going to be
automatically
set to zero.
And from there every member's value will be incremented by 1.
Now in terms of best practices I suggest always explicitly set values for these E-News
because it's
very likely that somewhere in wer database we might have a table that represents this enim.
So we want to make sure the IDs are the values we assign to these new members match to the
records
we have in the database.
If we rely on the automatic value assignment and sometime in the future add a new member
to this new
the value of some of the existing members may change and may no longer match the records
in the database
.
So
OK now we have a new we know it's a new type and we can use it when declaring a variable.
So in the main method
and here we use the dot notation.
Know that Intellisense shows us all the members and this we know.
So let's set it to express.
Now I told we that internally and Ino is an integer.
So I can easily cast that to an integer.
If I want the numeric value of this U.
So let's display the numeric value of this shipping method on the console.
So I put Methot here and then cast it to an integer.
Let's run the application.
So the value of Express is three.
Now there are times that we receive a number from an other system.
It could be wer database or it could be a third party application supplying some data and we
need
to convert that number that integer to a shipping method in wer application.
In situations like that again we can use casting to convert an integer to a shipping method.
Let me show we what I mean.
So imagine we received the number three from somewhere else
and we want to convert that to a shipping method so we can use casting shipping method and
put method
id here.
Let's look at the result.
So we see the number 3 represents the express shipping method.
So these are two examples to convert anti-New to and from an integer What about the strings.
There are times that we need to convert and to strings or get us rank and convert it to an
enim.
Let's take a look at two more examples here.
So I'm going to convert this method here.
Do we drink so Method dot look at these methods here.
Every object in C-sharp has a method called two string.
So technically we can convert anything to a string without doing any extra work.
So all I have to do here is just to call the two string method and when we run the application
we're
going to see Express on the console.
There we go.
Look at the third line.
OK.
No as a tip.
Cancel that right line by default.
Always calls that two string method on any value wer password tweet.
So in this example even if I didn't call to string console the right line would still convert that
to
a string.
But in case we're not using console the right line and we want to explicitly convert that enim
to
a string then we can use the two string method.
So I'm going to revert this back and find example when we have a string.
And we want to convert that to an enim.
Again the reason could be we have that string stored somewhere in the database or in another
system
.
So something like this we need to convert this method name to a shipping method
enumeration.
How do we do that.
Well before I show we that I want to introduce we to a new term parsing parsing.
In programming means getting a string and converting that to a different type.
So we say we parse the string.
Which means we convert that string to a different type.
So technically here I want to parse the string into a shipping method.
How do we do that.
Well we have a class in Dartmouth called ino.
This class is defined in the system namespace.
So if we don't have using system on the top of wer file we need to add that here.
Now this class has a number of static members.
So if we put dot here we can see it's static methods.
And look here we have a method called parce.
Let's look at the parameters of this method.
So open the parentheses again.
So this method has two versions which we call two overloads.
The first one takes two parameters.
The second one takes three parameters.
Let's take a look at a simpler one.
So the first promiser is a type object.
What is a type type is a classic Achmat that represents mental data above other types.
As a pragmatic tip whenever we see that type object we can use that type of operator.
So look type of this is a Keyworth.
This is an operator and takes a parameter.
So here we need to specify the target type that we want to convert the string to.
What is the target type here.
Our shipping method so shipping method here.
Now look at the second parameter of this method string value.
So here I pass method name.
Now look at the return type of this method.
It returns an object.
It does not return a shipping method.
So we need to cast this object to a shipping method which means I go to the beginning of the
line.
Use cast wer shipping method.
I know I can store the result of this expression into a different variable.
Let's call it shipping method.
Or forgot the semicolon.
There we go.
Now if I hover my mouse over var look the type of our variable is a shipping method.
So this is how we convert or parse a string to an enum or enumeration
OK so far we have talked about various data types and C-sharp.
We looked at primitive types like a major character float pool and a few known primitive
types like
classes structures arrays and strings.
And I told we earlier that both strings and arrays are classes.
So I showed we during one of the demos that this drinky word master the String class and
that and same
goes for the array notation that maps to their A-Class.
Now that brings us to an interesting topic.
And C-Sharp essentially we have two main types from which we create new types.
We have classes on one side and structures on the other side.
So every time we have learned so far is either a class or a structure.
So all primitive types are structures.
Remember I told we use the structures for small types like our G-B color and point well all
primitive
types are very small types.
They take no more than 8 bytes.
That's why they are internally defined as a structure in dot net arrays and strings are both
classes
.
We can also create custom classes like person or calculator.
Now in C-sharp these classes on structures are treated differently at runtime in terms of
memory management
.
And that's what I'm going to cover in this lecture.
I want we to understand what happens under the hood in memory.
So if wer program does not behave the way we expect we'll be able to troubleshoot it.
Structures are what we call value types while classes are reference types.
When we create a variable that is a value type a part of memory called Stack is allocated for
that
variable.
This memory allocation is done automatically so we don't have to worry about it.
When this variable goes out of scope it will immediately get removed from the stack by
runtime or C-L
or with reference types however we the programmer need to allocate memory werself.
Remember the new operator we use the new operator with classes.
So when we use the new operator we tell the runtime to allocate memory to this object.
And this happens from a different area of the memory called heap memory on the stack is
more sustainable
.
So if we create an object and that object goes out of scope it will continue to exist in the heap
for
a little while.
It won't be removed immediately.
There is a process called garbage collection which is done by runtime or C-L or that takes
care of this
.
So once in a while still are looks at the objects that are no longer used and removes them
from the
heap.
Now this was the theory behind value types and reference types.
What do we need to know in pragmatic terms is when we copy an object to a new variable
depending on
whether that object is a value type or reference type.
There will be two different outcomes and it's much easier to show this in code.
So let's flip over to Visual Studio and see how copying value types and different types are
different
OK in this video I'm going to show we a reference types and value types in action.
I'm going to use two different examples so I'm going to start with a simpler one.
First I'm going to create an integer variable
so I use 10.
Now I'm going to create another variable called B and copy A to B.
And finally I'm going to increment B by 1.
So I'm going to use the increment operator.
Now I got a question for we.
What do we thing the value of 8 is going to be at this point.
Is it going to be 10 or 11.
The answer is 10 because integers are value types.
So when we copy a value type to another variable a copy of that value is taken and stored in
the target
location in memory.
So let's verify this.
I'm going to use cancel the right line.
And here I'm going to display a and b on the console.
What is a good way to display and B we can use string format remember string format so
string not format
here resupply a format string.
So 0 and 1 here are placeholders and so play arguments to fill these placeholders.
So A and B here.
Now let's run the application with control and F5.
So look at use 10 and 11.
So the lesson is when we copy a value type to a different variable.
A copy of that value is taken and stored in the target variable.
That's why we call them value types.
Their values are copied.
Let me show we what just happened in memory.
So imagine here is the stack.
And somewhere in the stack we have a location identified by a.
And in that location we have the value 10 when we copy to be a new location in memory and
stack is created
identified as B and the value we had there in a is copied to be.
That's why these two variables are now completely independent and making a change to one
does not impact
the other.
Now let's see.
Reference types in action.
So this time I'm going to create an integer array.
And as we know in C-sharp an array is a class.
So it's a reference type.
So let's create array one
on here.
I'm using the object initialization syntax to initialize my array with one two three.
Now I copy this array one into another variable called array 2
and finally I'm going to make a modification to array 2.
So let's say I want to set the first element to zero
at this point what do we think is going to be the first element of array 1.
Is it going to be 1 or 0 it's going to be 0.
Let's go back to the memory visualization again and see what happens when we run this code.
So here we've got stack and heap.
When we create and initialize array 1 this is what's going to happen first an object is going to
be
created on the heap.
This object is in a memory location with that address.
We see here and inside this memory location we have the actual array with three elements.
One two three.
Next the runtime or ACL are create a viable on the stack identified as array one the value
inside this
variable or inside this memory location is a memory address and that's the address of the
object on
the heap.
The actual array.
So array want points or references.
The object on the heap.
So this is what happens when we create and initialize array one.
Now let's see what happens when we copy array 1 to 2.
So the runtime creates another variable on the stack identified as Array 2 and again inside this
variable
.
We're going to have a memory address.
And as we see in this picture this address is the address of the object on the heap.
That's why both array 1 and array 2 point to the same object.
Which means when we make any changes on this object on the heap either through every one
reference or
array two the changes are visible through the other variable.
That's why we call these types reference types.
So when we copy them there reference or their memory address is copied.
Now the actual value.
So back to the code.
Let's verify these.
Again I'm going to use Konsole the right line on the string the format
so I'll display the first element of both are A1 and array two and they both should be 0.
That's running application.
They both are zero
OK let's take a look at another example of reference types and value types in action.
So in this code I have defined a class called person with one field called H.
And inside our program class I have defined two methods increment and make Allt the return
type of both
these methods is voit which means they don't return any values.
And the reason I have defined both these methods of study is simply to call them without the
need to
create an object.
Just want to keep things simple.
So in the main first I'm going to create an integer called number
and I set it to 1.
Now I'm going to call the increment method and pass my number viable as an argument.
So the Inkerman method takes a parameter of type integer called number and adds 10 to it.
Note that here I'm using the addition assignment operator to add 10 to the number that is
passed to
this method.
Now at this point what do we think is going to be the value of our number in the main
method.
It's going to be one because this is a value type.
And when we passed these variable as an argument to the increment method a copy of this
variable is
taken and sent to the Inkerman method.
So interestingly even though these two variables have the same name but there in two
different locations
in memory one is the number with the scope of the main method.
So outside the main method this variable does not have a meaning.
And here we have another number coincidentally have the same name.
Inside the Inkerman method but that's a different place in memory and its scope is limited to
the Inkerman
method.
So when this increment method is called that new location is created called number.
Its value is incremented by 10 and then it's immediately destroyed.
Now let's verify this.
So I want to use console the right line and display number.
We run the application.
So our number is 1.
It's not affected by the increment method.
Now let's take a look at an example of a reference type.
So this time I'm going to use our personnel class.
So I create person object
and used the object initialization syntax to set its field.
So this person is 20 years old.
Now here we have another method called Make old that takes a person object and adds 10
tweets age of
field.
So note that here because the type of this parameter is a reference type the object that is going
to
be passed here is not going to be copied.
Each reference is going to be copied.
Which means both the person object we have the main method and the person object that we
have as a parameter
to this method will be pointing to the same object on the heap.
OK so if we call make old and past this person object upon returning from this method the
age of this
person is going to be 30 let's verify that.
So person the age and just run the application.
There we go.
That's it for this lecture.
I hope we enjoy it.
And thank we for watching
So in this section we learn that we have two main categories of types in C Sharp on one side
we've
got crosses on the other side we've got structures examples of class those are strings arrays
for any
custom classes that we create.
Examples of structures are all the primitive types like integer character float and any custom
structures
that we create.
The difference between the two types is purely memory management and we can review that
again in the
lecture hall reference types versus value types.
Now from the next section things start to get really interesting because I'm going to teach we
about
control flow and we'll be able to write simple C-Sharp programs and then in each section we
will learn
something new about C-Sharp and we'll be able to write more interesting programs.
So I was here the next section
Section 5:
This section we're going to explore conditional and iteration statements and C.
We use these statements to control the flow of programs.
So from this section we're going to start writing simple SUKAR programs.
Now I have designed a number of programming exercises that we can find at the end of this
section Whether
we're new to programming or been programming for a while.
I highly recommend we to spend half an hour if we are going through these exercises because
not only
will they help we remember the language syntax.
It will also train wer programming brain which is absolutely crucial if we want to be a
successful
programmer.
So go through the lectures and spend some time doing the exercises.
Now whether we solve the problem or get stuck I think still a good idea to look at my
solutions as
a different way of solving the same problem.
By the way my solutions are by no means perfect.
In fact there is no such thing as perfect in programming.
We give a problem to 10 different developers and each comes with a different solution.
So do wer best to solve the problem.
I look at my solutions for inspiration.
Now let's get started.
OK first I start by defining a viable and call it hour and send it to 10.
My intention is to define hour as a 24 hour time format.
Now I can say if our is greater than zero and it's less than 12 Konsole right line.
It's morning.
So as we see I put the expression here that is a boolean expression I'm using and here.
So these two conditions will be evaluated and if both are true then these will be executed.
Now I can have another condition.
So I write.
Else if our is greater than or equal to 12 and it's less than 18 which is 6 pm right line
afternoon
.
And finally I can have an else statement.
So if none of the earlier conditions is true then this piece of code will be executed.
So it's evening as I told we if we have more than one line of code we need to enclose them in
curly
braces.
But some people say even if we have one line of code it's good practice to put them in curly
braces
like this.
Similar here
they go.
Let's run this program is in control and F5.
So it's morning.
In this case because the hour was 10 this condition was evaluated and it was true.
So this piece of code was executed.
Now let's take a look at conditional operator.
I'm going to change this piece of code.
So first let me clean this up with the sharper we use control and double we to select some
piece of
code like this.
It's really easy.
It's much easier than putting the cursor here and using shift and down arrow like that.
So anywhere we are in the code we can just control w to select a piece of code or keep
extending wer
selection like this.
OK.
Now let's take a look at conditional operator so I can define a ball.
Say is gold customer and set it to true.
I want to say if is gold customer I want to have a float here.
Call it price.
And here I say price is going to be nineteen ninety five dollars.
Otherwise price is going to be twenty nine ninety five dollars.
Now I can rewrite this code using a conditional operator.
So I would say float price equals put the condition.
Here is gold customer followed by a question mark.
Now if that condition is true what do I want I want.
Nineteen ninety five dollars else is specified using a colon.
The price is going to be twenty nine ninety five dollars.
And of course I can't get rid of this.
I just commented.
I keep it here so we can see them for comparison.
And finally put the price on the console.
So let's review one more time.
That's the condition.
If that's true then what we have after question mark and before the colon will be executed.
So 1995 will be returned and assign to the price variable otherwise is specified using a colon.
And here what we put here will be returned and set to the price here.
So is it just a shortcut to write an IF statement let's run the application.
So the price is $19 because I am a customer.
Now let's take a look at switch case.
So with resharpen I use control and W to select everything here and clean it up.
So actually let me define an enumeration first
public income season.
So we have four seasons.
Spring Summer Autumn and Winter.
In this case we don't really need to give an explicit value to each of these items here because
we're
not working with a database or an external application where there is a numerical
representation for
the seasons.
So if we just leave it like that and to keep my code clean I would like to put this in a separate
file
so we'd resharpen what I can do is I put the cursor here.
And as we see I've got this marker here.
So with Altan enter I can activate that and press enter and move it to another file.
If we don't have resharpened Why do we need to do is to go to solution explorer here.
Right click wer project go to add new item.
And here we select a class to add a new class.
Let's call it Season 2 because I already have a file called season that's yes.
So I put that new class here.
Now I'm using an enumeration model class so I can get rid of this and then I can just go here
and copy
this piece of code and put it into the file here.
So as we see it's much easier and faster to use resharpen.
All right.
I'm just going to get rid of this file
and delete it here.
OK.
So we define an enumeration called season with or values here.
Now let's go to program.
I'm going to define a variable this time I'm going to use var college season.
Set it to season dot autumn.
Now let's put a switch on season so each season.
So we put the variable in parenthesis.
Here we have a block and we can have one or more case statements.
I can say if season is season the autumn display on the console it's autumn and a beautiful
season.
I termly this case block with a break statement.
Now I can have another case statement here if season is summer.
Customer writes line say it's perfect time to go to beach and break.
Finally I can have a default here so if the season is none of his values I can say I don't
understand
that season.
It's a little bit stupid but that's just for demonstration.
And of course we need a break statement here.
Let's run this application now.
So it says it's autumn and a beautiful season.
Now let me show we something.
Let's say in autumn and summer we would like to have a promotion.
So instead of displaying this message here we would like to say something like we've got
promotion and
I would like to have the exact same message appear if the summer if the season is summer as
we see
this piece of code looks like a duplicate.
It's not a good thing.
What we can do here is to get rid of these statements here and have these two case statements
next to
each other.
Note that the first one got nothing next to it and the second one has the actual code that will
be executed
.
So in this case what that means is the if the season is autumn or summer then this piece of
code will
be executed.
Let's run the application.
We've got promotion.
That's it for this video.
I hope we enjoyed it.
And thank we for watching.
OK.
Earlier we wrote this simple program to display the list of even numbers between 1 to 10
using a for
loop.
And they told we during the slides that we can write the same code with for a while or do Y
loop.
So now I'm going to write the same program using a while loop because before we get started
I want to
comment out this code.
So
OK first let's declare a counter variable.
So I.
Is zero while I is less than or equal to 10
now or condition
will display I on the console.
If it's an even number and here we need to increment I buy one.
So this is the exact same code but written using a while loop.
Now in this case I prefer to use a for loop or the scenario because typically we use the for
loop when
we know the number of times we would like to do an iteration.
So it's cleaner to declare that count viable like I.
When we are declaring the four block as opposed to outside the wire loop as we have here.
OK.
Now we might be wondering when do we use the while loop.
Well there is no hard and fast rule but typically it's better to use a while loop when we don't
know
ahead of time how many times we're going to do an iteration.
Let me show we an example here.
So first let me clean up this code.
We want to write a simple code program and this program we're going to display a message
on the console
asking the user to type their name if the user types the name the console is going to repeat or
a code
that name.
But if a user simply presses enter without typing a name the program is going to terminate.
So in this case we don't know ahead of time how many times the user is going to use the
program.
How many times are we going to echo in that case it's better to use a while loop.
So how do we do that.
So in this case we are not going to have a counter variable.
So instead what I'm going to do.
I'm declaring a while and in that condition I'm just going to use True which means this loop is
going
to execute forever.
Let me display a simple message on the console so console that.
Right.
So I'm going to use the right method instead of right.
The difference is the cursor is going to be on the same line.
We're not going to have a line break.
So Type wer name let me run this program and see what happens.
So we see this program is executing forever because that why loop is not terminating and the
program
keeps displaying type wer name.
So let me terminate this.
So at this point we need to read something from the console.
So we use console not the read line method and this method.
Take a look at it signature.
So I remove the parenthesis.
I open it again.
Look at the tooltip.
This method returns a string.
So we can store the result in a string called input.
Now if the user simply presses enter and do not type a name that input is going to be an
empty string
or if that's the case it's the time to jump out of the loop so to check if a string is empty.
We often use string dot is null or whitespace method.
This method expects a string and returns a boolean value.
So if input is null or whitespace then this condition is true.
And then at this point we're going to break and we break.
We jump out of a loop.
Otherwise if that does not happen we want to echo the name.
So cancel the right line echo.
And now we are going to append the input here.
Let's run this application.
So Type wer name.
Marsh echo Marsh.
Note that the program continues execution but this time I type John and it echoes John.
Now this time I'm going to press enter and the program terminated.
One of the questions beginners ask me is how does this press any key to continue up here
here.
I didn't write any code for that.
When we run wer application using control and F5 by default when the application terminates
the console
displays that message for we.
OK now I'm going to change this program a little bit so we can learn about the continued
keyword.
So what I'm going to do here is I'm going to apply and not operator here.
So if the input is not now or whitespace in that case we want to echo it right.
So let's not worry about this break.
I'm going to move this concept the right line here.
Now I'm going to put that break here.
So what do we think is going to happen now.
When we were on application first we get this message type wer name we type a name.
Of course it's not Nailor whitespace.
We're going to get an echo.
But then we get to this statement and that causes the loop to terminate.
So this program is going to execute only once.
How can we change this so it can behave like before.
That's when we use to continue a keyword.
So I'm going to put the continue here and let me explain what happens.
So at this point after we call the name when the program sees this continue instead of
continuing here
it's going to continue to the beginning of the loop.
So we get by here and the condition is true.
So the loop continues to execute.
Let's run the program.
Type wer name.
Marsh.
The loop is continuing.
Type wer name John.
Now this time just press enter and the loop terminate.
So as usual we can write the same program in different ways.
Sometimes we may apply and not operator and because of that we may have to use the break
or continue
which one is right which one is wrong.
There is really no right or wrong.
We need to do wer own judgment which code is more readable and more understandable.
And this video I'm going to show we a useful class we know in dot net framework which is
called random
.
We use this class to generate random numbers.
So first we create an instance of the random class.
This class has a few useful methods.
Next we took turns around a manager next bytes which takes a bite array and fills it with
some random
numbers so we can create a byte array of any size pass it to this method and this method will
fill
that byte rate with some random numbers and next double which returns a random double
between 0 and
1.
Let's take a look at the next method.
This method has three overloads as we see on the screen.
The first one takes no parameters and it simply returns a non-negative random number.
So let's create a for loop and generate a few random numbers and display them on the console
.
OK let's run the application.
So we see some random numbers here.
Now there is something interesting we can do with the next method.
Let's take a look at this method again.
The second overload takes a maximum value.
And the third overload takes a min and max value.
This is very useful when we want to limit the range of random numbers.
So if we want to create random numbers between 1 and 10 we simply supply them here.
Let's run the application again.
So now we have random numbers between 1 and 10.
We can use this technique to even generate random characters like random passwords.
Each character internally is represented using a number.
Because computers don't understand characters and letters they understand numbers.
Let me show we what I mean by that.
So I temporarily comment this out and all I want to do is display a character a on the console.
But I want to cast it to an integer.
We got 97.
So 97 is the standard number to represent a lowercase a in a computer.
This was first introduced as ASCII which stands for American Standard code for
international interchange
.
Let's take a look at this Web site Aski dash code dot com.
So in this table we can see the letters like let me show we here like.
Plus we know all these numbers are alphabets in a uppercase a to that Laura case.
See all these characters have a number represented in decimal format which is here.
And they also have a binary representation.
This is eventually what the computer understands.
Now if we look at 6:51 we see Alora Casey.
And let's take a look at the Zad.
So that is Hundred and 22.
So what this means is if we generate a random number between 97 and 122 and then cast it to
a character
we'll get around no character and we can repeat this a few times and generate a random string
like a
password.
Let's give it a try.
So let's bring this back in.
What I want to change here is limit the range to 97 and 122.
Now if we run this application we are going to get a number coming from the next method.
So we need to cast the true character
and I'm going to change right line to right because I don't want this character to be on a new
line
.
Let's run the application this press any key to continue message is missing up with.
Also let me add a constant the right lane here so we can see more clearly.
There we go.
So here's a random string.
Now a tiny problem with this code is, if someone look at this code.
They have no idea what is 97 and 122.
So let me show we a more expressive way to write the same code.
What we can do is replace that with 0 and 26 because we have 26 characters in the English
alphabet.
Now we get a number between 0 and 26 if we had that number two character eight.
What do we think is going to happen.
Well this is a character.
And internally it is represented as a number.
And when we add this character to a number the result is going to be a number.
Then we cast it to a character.
So eventually we get the same result.
A random character
now in the real world we don't want to create a random string and displayed on the console.
Most likely we would like to store it in a string but there is a tiny problem here.
In the last section I told we that strings are immutable which means once we create them we
cannot
change them.
Of course there are methods that we can play on a string and we get an updated value.
But in every case the original string is not affected.
We always get a new string.
So in C-sharp we cannot create a string and set each individual characters using a random
character
.
But what we can do instead is to store this result in an array and then create a string based on
that
array.
Let me show we how it works.
So
first I declare a character array let's call it buffer.
And because we're are generating 10 random characters here I'm going to set the size of this
or eight
to 10.
And of course we can use var here.
And as we see the green highlight is indicating that the code is cleaner now instead of
displaying
each character on the console.
Because simply stored in the buffer.
So let's get rid of this console right and
store it in the buffer.
So I'm using I the loop counter variable to access an element in the buffer every now and the
last step
is to create a string based on that character array.
Now most of the time we create a string like this.
So we use a string literal but there is a less common way to create a string and C-Sharp is not
something
that we use everyday but it's good to know that as something in wer toolbox so use the new
operator
if we remember from last section the string keyword maps to a string class in the dot net
framework
.
And we know that with classes we can create an instance of them using the new operator.
So we can't do news Stream.
And look here in the constructor of a string we have a few overloads.
The last one as we see here takes a character array.
So if we pass our buffer here we will get a string based on the character orrery.
Now we can display this password which is a string on the console.
Look we've got the same result.
One last thing I would like to add here to improve the quality of this tiny little code and that
is
I don't like this magic numbers here 10 here and 10 here.
The problem with this is if tomorrow we decide to change the length of our random password
we have to
come here and change this 10 to 8 and we have to remember to do this here as well.
So a better way is to declare a constant like password length.
Set it to 10.
We can use that to create our array.
And of course using it in the for loop.
The code is more expressive and more reliable.
So that's all we need to know about random class.
I hope we enjoy this lecture.
And thank we for watching
Okay at this point we know a little bit about race in this section.
I'm going to expand wer knowledge of bag arrays and introduce we to multi dimensional
warriors.
This is useful if we're working with structures such as a matrix.
I'm also going to talk about generic lists which are very useful in building real world
applications
.
Again similar to the last section I have designed some exercises to help we train wer
programming
brain.
So be sure to go through the lectures and spend half an hour doing wer exercises.
Now this started
Earlier in this course we learn a little bit about race in this lecture.
We're going to take a deeper look at race.
So first I'm going to have a quick review of arrays then I'm going to talk about different types
of
arrays we have in C-sharp.
And finally I'm going to introduce some useful methods to work with arrays.
So just to refresh our mind an array represents a fixed number of variables of a particular type
in
C-sharp we have two types of arrays.
Single dimension arrays and multi dimensional race like a matrix.
So single dimension arrays is what we have seen before in this example.
We have an array of integers called numbers and the length of this array is five.
If we know ahead of time the values we would like to store in an array we can use the object
initialization
syntax to initialize that array.
Upon declaration.
So nothing new so far.
Now let's take a look at the types of multi dimensional race.
We have two types of multi dimensional arrays in C Sharp rectangular and jagged race.
So with a rectangular array each row has the exact same number of columns.
So in the example we see in the slides we have an array of three rows and each row has five
columns
with a jagged array.
However the number of columns in each row can be different a different way to look at Jack
array is
an array of arrays.
So we can think of the Jack the array we have in this slide as a single dimensional array with
three
elements and each element is another single dimension array.
Now what's the difference.
When do we use a rectangular array or a jagged array in dot net CLR is optimized around
single dimension
arrays.
So let's say we want to model a matrix is faster to implement it using a jack array than a
rectangular
Arri.
I mean we said that the difference might be really tiny.
Specially with the computers we have these days.
So my pragmatic advice to we is don't get stuck about the difference between rectangular and
jaggery
too much.
Just be aware that in the future we have two types of multi-dimensional race.
Now let's see how we can declare a rectangular array.
So here is the syntax for declaring a two dimensional rectangular array.
So the only new thing we see here is that in the square brackets we need to specify the
dimensions
of the tree.
So in this case this array has three rows and each row has five columns.
If in know the values we will like to stirring this array ahead of time we can initialize this
array
using object initialization syntax.
And if we want to access an element in disarray just like before we use the square brackets.
But we need to supply the index of the row and the column if we want to declare a three
dimensional
array.
We can extend the previous example and supply three dimensions while declaring the array.
So in this example our colors array has three dimensions.
Now let's take a look at the jaggery.
So imagine we want to model an array that looks like this.
So as I explained earlier we can think of this array as an array of arrays.
So at a top level have a single dimension array of three elements in each element.
We have another single dimensional re.
So in our first element we have an array of four elements in the second element.
We have an array of five elements.
So how do we implement this.
Well first we need to declare a top level array not the syntax here.
We use two square brackets to represent it jaggery in the first square brackets we specify the
number
of elements in wer toplevel array.
Now we need to initialize each element of this array to a different array.
So we're supposed to find that the first element of this array is another integer array of size 4
and
to access an element in this array.
Again we need to add square brackets.
So the difference between the Jagd array and rectangular array from the same tactical point of
view
is that we jaggery we have two square brackets whereas with rectangular array we have one
square brackets
.
But we separate the dimensions using a comma in C-sharp.
All arrays map to the array type that is defined in the system namespace of Doc net
framework.
So the array type is a class it has a bunch of properties and methods as we see in this slide.
OK.
Now let's flip over to Visual Studio and see all these concepts in action.
So in this video we're going to take a look at some of the useful properties and methods of
our race
.
Let me start by creating an array of integers and call it numbers.
So in theory numbers equals new in theory and I'm going to use the object initialization
syntax to immediately
initialize Asare So some random numbers here like 3.
Now notice green on the line here.
Sharper is suggesting to use voire to make the code cleaner.
So I put the cursor here Altan enter and enter also here.
Note that it is great out.
Which means it's not necessary.
So we can keep the code even shorter.
So again Alt and enter and enter.
Now let's take a look at the length property
length returns the size of the array.
So in this case we have six elements in the array.
So the size of the array is six.
So cancel the write line
.
Let's run the application.
So we got 6 on the console.
Now let's take a look at the next of method we use this method to find the position of an
element in
the array.
Let's say we're looking for 9 so we can use this method like this every dummy index of.
I opened the bracket look at the tool.
There are different ways to call this method and that's what we call method overloading.
So in this example this method has five overloads or five versions.
I'm going to use the first one which is the easiest.
So look at the first parameter.
That's the array that we're going to do searching.
The second parameter is the actual object we are looking for.
So I press escape past my numbers array here and as the second argument I'm going to pass 9.
This method returns an integer.
So I'm going to store the result in a variable called index.
Let's display index on the console
.
So the index of 9 is 2.
Which means it's the third element in the array because in C-sharp the index of the first
element in
an array is 0.
Now let's take a look at the clear method
.
So this method has three parameters.
The first element is the array.
So I pass numbers here.
The second parameter called index is the starting index of the range of elements to clear.
Let's say we would like to clear the first two items.
So I'm going to pass 0 here as the starting index.
And the third promotor is the length which is the number of elements we will like to clear.
So I'm going to pass two here.
Now I'm going to iterate over this area using a for each block and display all the elements.
So let's take a look at the effect of clear method.
Note that the first two items are set to 0 and that's the meaning of clear.
So in this example because our array is of type integer clearing these numbers means setting
them to
zero.
If we have an array of booleans clearing that means sitting some of its items to false.
And if we have an array of strings or other kind of objects clearing the items in that there are
a means
saying them to now.
OK now let us take a look at the copy method
.
So this method takes three parameters.
The first parameter is the source array.
The second parameter is the destination and the third parameter is the number of elements we
would like
to copy.
So before using this method I need to declare another array
so this is a smaller entry.
It has only three elements.
So I'm going to copy the first three numbers from our numbers are eight in into are another
three.
So
and now just explain the result on the console
and run the application.
So notice that after we the copy method the first three elements in the numbers array which
were here
are copied to a second array.
Now let's take a look at the sort method
.
This method again has five different versions.
I'm going to use the first one which is the easiest.
So I simply pass on another array.
Let's display the result on the console
and or on the application.
Actually this was not a good example because our secondary was already sorted.
So I'm going to apply this sort method on our original array.
So.
And we need to change that in the for each block.
Let's try an application again.
That's better.
So we got 0 0 2 6 9 and 14.
And one more method to explore in this lecture is the reverse method
.
OK let's run the application.
So here is the effect of the reverse method.
OK.
Before we finish this lecture through a couple of things I need to point out here the first one is
look
at the first example where X is the length property of the numbers object whereas in other
examples
all the methods we called like Index of what's called on the array class itself not the numbers
object
.
So what is the difference.
The difference is if a method is accessible on the class itself like array that means it's a static
method.
We're going to take a look at the static members later in this course.
For now just remember when a class member like a method or field or property is declared as
a static
that means it's accessible from the class itself but otherwise that member is accessible via the
object
.
So let me show we an example here.
If I type array dot These are all the starting methods defined in the array class.
But if a type number is dot These are the members that are not static.
There are instance members which means they're accessible by an object.
So if I type it in X of here we see there is no method called index off or if I typed clear there
is
no such a method called clear.
That's why it's only accessible from the array class.
Now we may be wondering how did I know which member is a static and which member is
not.
Well part of that is experience.
But if we try to access a memory and we can find it wer best help is Google simply go to
Google.
Now let's say we are looking for the sort method of the Array class.
Simply type C-Sharp or a sort.
And the first method pretty much in every single case is the documentation on the MSDN
Microsoft Developer
Network.
So if we go here
this is this standard documentation of the sort method of the Array class in darkness
framework.
So we can see all different ways of calling this method.
That's what we call overloading remember.
So a method can have different overloads which means it has different versions.
So note that all these methods have a red as in front of them.
That means it's a static method.
Now let me show we the array class itself.
So if we scroll down we go to air class
I know that these properties here they don't have that red S which means they're not static or
instance
members for instance properties.
I look most of these methods except clone and copy to here are static.
So whenever we get stuck to jump on google type C-Sharp and then type the name of the
class and the
name of the method.
I hope we enjoy this lecture.
And thank we for watching
And the last lecture we learn about a race we learn that in C-sharp arrays have a fixed size
which
means once we create them the size cannot be changed.
But there are situations where we need to work with a number of objects but we're not sure
ahead of
time how many of those objects we're going to work with.
That's where we use a list elist in C-sharp is similar to an array in a sense that it's a data
structure
for storing a number of objects of the same type.
But we use a list when we don't know ahead of time how many objects we're going to store in
that list
to create a list.
We use the list type list is a generic type.
And that's indicated by the angle brackets.
As we see in this example inside the angle brackets we specify a generic prompter and that
parameter
specifies the type of the list.
So in this case I'm creating a list of integers.
We can create a list of anything we can create a list of strings or a list of characters or a list
of any non primitive types.
We can create a class called product and create a list of products.
Generics is an advanced topic and for now that's we know for we to know that when we are
working
with a generic type we need to specify generic parameters inside the angle brackets.
And the third part of this course C-Sharp advanced.
I'm going to cover generics in more detail if we know ahead of time the objects we would
like to store
in the list.
We can initialize wer list using the object initialization syntax as we see here.
So we put the objects between curly braces during initialization of wer list.
And here are some useful methods that are available in the list class.
I had to add an object to the list add range to either list of objects that can be another list or an
array remove to remove one object from the list remove at which removes the object and the
given index
index of which returns the index of the given object contains.
Which tells us if the list contains the given object or not and count which returns the number
of objects
in the list.
Let's really go over to Visual Studio and see all these methods in action.
I'll write this for we I'm going to show we how to work with lists or more accurately generic
lists
and C-sharp.
So let's create a list.
We use the new operator to initialize an instance of the list class.
Note the angle brackets here in the intellisense that indicates that list is a generic type.
I also know that it's defined in-system that collections that generic if we don't have RRE
sharper
than Intellisense we see is going to be different.
I don't think we're going to see the namespace which means we have to go on the top of the
file and
type using system that collections dot generic.
Once we import the namespace then we can come here and create a list.
We specify a type here.
So let's say we would like to create a list of integers.
That's it we can initialize this list ahead of time using the object initialization syntax.
So I'm going to supply one two three four here.
Now we can add something to this list.
So numbers start at.
I would add another one here.
So this is the difference between a list and an array in an array.
We don't have an Add method and once we create the array the size of the array cannot be
changed but
in a list we can add as many objects as we would like.
We can also use the Add Range method to add more than one object to the list.
So numbers don't add range.
And note that in the intellisense here we see it in wer Mirable of INT What is I enumerable.
Well first of all whenever we see a type that is prefixed with I that is an interface I have
covered
interfaces in detail in the second part of this course.
So for now we want to keep things simple.
I want to give we a quick tip here.
Whenever we see I enumerable in the intellisense sincerer we can use an array or a list there.
Once we understand interfaces in the second part of this course then we'll realize that that
interface
is implemented by different classes like the array or the list which means whenever we see I
enumerable
we can supply an instance of a class that implements enumerable.
Now if all that sounds too complex Don't worry about it.
Again remember my tip.
Whenever we see enumerable we can use an array or a list so that we creates an array here.
New Interrail.
I'm going to specify the size of three and I can use the object initialization syntax to
immediately
initialize history or 8 5 6 7.
Now it's very unlikely that we're going to write code like this in a real world application so
don't
be intimidated by this weird way of initializing a list.
All I want to show we here is the number of possibilities when working with lists.
We don't have to memorize anything.
All I want we to take away here is an idea of what we can do with a list so we can create a list
like here.
We can initialize it ahead of time if we know the objects we want to store there.
We can call the add method to add one object to a list or we can call add range to add another
list
or an array to the list.
Now once we have a list we can.
I tried it using a for each loop so for each bar number in numbers cancel the right line
number.
Let's run the application.
So we got 1 2 3 4 1 5 6 7.
Now let's take a look at the index of method.
So numbers dot indexOf this method as a few different overloads.
The simplest one which is the one that is currently highlighted.
Means we can press an item of type integer here and this method returns the index of that
object in
the list if it exists otherwise it returns minus one.
The second overload of this method takes another parameter called index and that's the
starting point
.
So we can say search or search from index 3 and the third overload of this method specifies
the number
of objects to include in the search.
The first overload is what we would be using most of the time.
So let's see was the index of one going to display on the console.
Let me add a label here.
So index of one.
And I would like to have a concert the right line here to separate it from our for each loop.
So Enochs of one is zero.
But interestingly we have two ones here.
Here's the first one.
And here is the second one.
We have another method called last the index of let's take a look at that one.
So I'm going to duplicate this line and instead use the last index of one let's run the
application
.
So last the next or one is four.
So sometimes we may want to start wer search from the beginning of the list.
In that case we use index of method.
Sometimes we might start wer search from the end of the list when in the real world does that
happen
.
I can't really tell we now because it really depends on the algorithm we're designing.
Now let's take a look at another useful member of the list class count so count numbers dot
count.
So this is a property that returns the number of objects in the list.
Let's run the application.
So currently we have 8 objects in the list.
Now let's take a look at the Remove method.
So numbers does remove I'm going to remove one from the list.
Now let's iterate the list again and look at the result after removing one.
So I'm going to copy this for each block and put that here.
Now let's run the application.
So note that the first one is gone but we still have another one.
What if we wanted to remove all the ones in this list.
So one way to do that is to use the for ish look.
So let's change this example to something like this
.
I tried to list one object at a time.
We'd check if number is 1.
Then very move number.
Once we do that let's copy this for each loop again
and put that here.
Let's run the application
application crashed.
Why be good and unhandled exception.
Me here.
This is an exception or an error that we may see from time to time when we're removing an
object from
a list inside a for each block.
So look at the exception detail here.
It's of type system to an invalid operation exception.
And the message says collection was modified enumeration operation may not execute.
So what this means is in C-sharp we are not allowed to modify our collection inside a for
each loop
.
So inside this 4 ish block we have these numbers that remove which is modified to collection.
So how can we change this program to get the desired result without that exception.
We need to use a normal for loop.
So something like for var Y is zero.
Run this as long as I use less than numbers that count then plus Bloss.
And we move this code here.
Now here we need to change that to numbers of.
Because we don't have a local variable like that for each called number.
Right.
So we need to access the current element in the list using an index numbers of why.
OK let's run an application.
There we go.
So we removed both ones from the list.
And one last method before we finished this lecture.
So let's take a look at the clear method numbers that are clear.
So this method removes all elements from the list.
Now if a display count on the console we're going to get zero.
So I'm going to grab this line here and paste that here.
So look the last count is 0.
So this was an introduction to the kind of things we can do with the list.
I hope we enjoyed this lecture and thank we for watching.
OK this section we'll learn more about C-Sharp race we'll learn that in our array's a fixed size
which
means once we allocate them we cannot change their size.
So if we want to work with a dynamic array we need to use a list now these days.
Ninety nine point nine percent of the time we use lists not a race but we might be working
with a third
party library or a legacy code base.
And we we still have to use arrays.
So remember the syntax I'd prefer for use lists.
I hope we enjoyed the section.
And thank we for watching
A.S. I want to teach we how to work with dates and times and C-sharp.
And as part of this I'm going to introduce we to two new types in darknet day time and time
span.
So let's get started.
OK this video we're going to take a look at how to work with dates and times in C-sharp.
We have a type called day time which is a structure that is defined in system name space so
type date
time and we see the structure icon here and that is defined in the System namespace.
So there are a number of ways to create a data an object.
One way is to use the new operator so they time because new day time and the constructor of
the structure
has multiple overloads.
So look at the first one here.
We can specify year month and day or if we want to be more specific we can go up to hour
minute and
second it has a bunch of different constructors so we got to keep it simple.
2015.
January 1st if we want to get the current date time wer access date time Dot now.
So now is a static property of time structure.
So I'm going to stored in a variable called now.
Or if we just want today's date irrespective of the time we can use date time Dot today.
Now that we have a datum object we can access it's components like year month day minute
hour very easily
.
So here's an example.
Now that hour or now a minute.
So let's put a label next to it
and run the application.
So currently it is 12:40 p.m..
So there are a bunch of properties that we can access.
I'm not going to go through each of them because I don't want to waste wer time.
But we've got the point.
One thing we need to know about data objects and share is that there are immutable which
means once
we create them we cannot change them.
So how do we modify them.
There are a bunch of methods and they all start with ADD.
So now Doug.
And so we can add days hours milliseconds minutes and so on to an existing day time
outright.
So let me show we add days 1.
So this returns tomorrow.
Current time.
What do we want to go back in the past.
We use a negative number.
So yesterday it was now that days minus 1.
Very simple.
And one last thing we need to know what daytime objects and C-Sharp is formatting them to
a string
.
So a data object has a bunch of methods for converting it to a date or time string.
So here are a few examples.
Now not too long date string I'm going to duplicate this line a few times.
There's another one too short date string to a long time string.
And two short time strings.
Let's see the difference.
I'm going to comment on these two lines so we can focus.
Let's run the application.
So note that with the first two we only have a date component and not a time whereas with
the last
two there is just a time component.
And obviously this is the long date.
And here's the short.
Now what if we want to display both date and time.
We use two string methods.
So
two strings.
Let's take a look.
So here is the current day time.
We also have this concept of format specifiers.
So to string method optionally takes an argument and here's where we provide a format
specifier.
So take a look at the intellisense here
what we see on the left side is a format specifier.
And on the right side we see an example of that.
So let's take a look at this one where we display a date with the hash notation.
This is very common in passing in SML or Jason.
So take a look at this one.
So if I want to output my day time to something like that we can use this string as the format
specifier
so I can use y y where a 2 digit year or four Y is for a four digit year.
I can use double M and double D.
Let's run the application.
But here's the result.
We can also add time to it.
So I'll take a look.
Double H colon double M.
So currently it's 12:46 p.m.
There are a bunch of format specifiers and we don't need to memorize them if we want to
look at the
full list so them simply go to Google and search for C-Sharp they time format specifier.
And the first link custom date and time format strings
.
So here we can see various examples of these format specifiers.
Their full list and examples for each of them.
In the last lecture we learned about daytime which represents an exact date and time value.
We also have a type called time span which represents a length of time.
There are a few different ways to create a time span.
The simplest one is to use the new operator so the time span calls new time span.
I know that the constructor has multiple overloads.
In this case I'm going to use the third one which takes hours minutes and seconds.
So let's say one hour two minutes and three seconds.
What if we didn't have a value for minutes and seconds we could just pass zero.
So here's an example
.
One hour zero minutes zero seconds.
The only issue here is when we look at this time span object sometimes it's not quite clear
what do
these zeros represent.
Is it the hours minutes.
It's not quite clear.
So a more reliable way to create the same time span object.
We use two static methods on the time span structure.
So time spent as a bunch of static methods and they all start with from from days from hours
milliseconds
minutes seconds and ticks.
So I can just use from hours and pass on here.
I note that between these two lines.
The second one is more readable.
There is also a third way to create a time span if we have two Daytime objects and we
subtract them
.
The result is a time span.
So something like this
.
So and mine start returns a time span and escapes that time span represents two minutes that's
displayed
on the console
.
So here's the result.
Two minutes and it has a slight millisecond value.
I think it's because of the day time that now.
So at the time that we read this value there was a tiny millisecond component in the current
day time
.
OK.
So this is all about creating time span objects.
Now once we have a time span object we can read its properties very easily.
So each time span has a number of properties that come in pairs.
What do we mean by that.
Look at this time span it has properties like days hours milliseconds minutes seconds and so
on.
But it also has paired properties that start with Total.
So total days total hours milliseconds and so on.
What is the difference.
Let me show we with an example.
So
I'm going to duplicate this line and this time I'm going to display total minutes.
So the minutes property returns the minutes component of wer time span object.
So in this case our time span is here the minute component is two.
So that's what's returned from minutes total minutes converse or time span object to minutes.
So in this case it's going to return one hour which is 60 minutes plus two minutes plus three
seconds
which is a fraction of a minute.
So let's take a look at the result.
So as we see meannesses to rest total minutes is sixty two point three or five.
Next
similar to the daytime object.
The time span is immutable which means once we created we cannot change it.
But it provides a couple of methods to modify its value add and subtract.
Both these methods return a new time span.
So let's take a look at a couple of examples.
So what I'm going to do is this time I called Add method.
Note that this method takes a parameter of type time span.
So here I can create another time span.
I can either use the new operator or I can use one of the static methods.
So let's say time span from minutes.
So I had eight minutes to our original time span.
So it was one hour two minutes and 30 seconds.
So now it's going to be 1 hour 10 minutes and three seconds.
There we go
subtract it's very similar.
So why duplicate this line subtract.
Again this method takes a time span object so let's subtract two minutes from our original
time span
.
And the result should be one hour and three seconds.
There we go one hour and three seconds.
Now one last thing we need to know about time span is conversion to and from strings.
So let's scroll down
if we want to convert the time span to a string we simply called the two string method
.
But note that in this case two string is greyed out.
What does it mean.
That means Konsole the right line by default calls this method on any object we pass to it.
So we don't have to explicitly call it.
But if we're not using in the right line and we need to convert a time span to a string value
simply
call to a string.
How would conversion from a string.
We use the Parse method.
So
time span does parse that takes a strange.
So let's say one hour two minutes and three seconds and then returns a time span object.
In this case we pass this time span object icons on the right line.
And this method automatically applies to string on our time span object.
Let's take a look at the result.
There we go.
So parse one hour two minutes and three seconds.
That's pretty much all we need to know about time span.
I hope we enjoyed this lecture.
And thank we for watching
So in this section we learn about two new types in .net Day time which represents a point in
time and
time span which represents a generation.
We remember both these types are structures that are immutable which means once we set
them we cannot
change them.
So let's say if we create an instance of a time and call one of its methods like add month or an
hour
in all cases these methods return and we instance I hope we enjoyed that section.
And thank we for watching.
Earlier in the course we learn that in C-sharp the string key word maps to the String class in
the
Dot Net framework.
So a string is a class and we also learn that strings are immutable which means once we
create them
we cannot change them.
In this lecture I'm going to cover a bit more details about strings.
I'm going to introduce we to some useful methods to work with strings and then I'm going to
show we
how to convert a string to a number and vice versa.
So I've categorized these methods into different groups in terms of formatting wer string.
We can use to lower to convert all characters to lowercase or we can use two upper four
converting
that to uppercase trim is a useful method which gets rid of the white spaces around a string.
And this is important and when we capture user inputs in web forums or Windows Forms if
we want to
search for a character or a string inside a given string we can use the index of or last index or
method
.
Both these methods have overload and they accept it or a character or a string and then return
an index
of the first or the last occurrence of the given character or a string in wer string
if we want to create a substring from a given string.
We use the substring method.
This method has a couple of overloads.
One that takes start the next and then retrieves all the characters from that point onwards to
the end
of the string.
The utter overload takes a lengthy argument to limit the number of characters to retrieve
if we want to replace a given character or a given substring in wer string.
Or use the replace method.
We have a couple of methods here.
Is not empty and is null or whitespace.
And that's a common way to compare a string against now or empty string or whitespace.
If we want to split a string we can use the splayed method in this example.
I'm splitting a string by an empty character which means if we have a sentence with multiple
words since
there is a empty character between each of these words they will all be split.
And what will be returned from this method is an array of strings each element containing a
word.
It's a very common technique to summarize a long string into a smaller one.
I was sure that in the coding demo
there are times that we get a string representation of a number and we need to convert it to a
numeric
value.
For example in most applications when the user types in a number into a text box we always
get a string
.
Even if that string is a number so we need to manually convert that to a number.
There are a couple of different ways to achieve this.
We can use integer to parse or we can use convert to in 32.
I personally prefer convert to 32 because if the string is now or empty this method returns the
default
value for the integer which is zero.
Whereas instead parse throws an exception.
So it's easier and safer to work with convert to 32.
And finally if we have a number and we would like to convert it to a string we can use that to
string
method on that number we can call this method without any arguments.
Which means we can get a string representation of that number or we can format that number
using a
format string.
So in the third line here C is a format string and that's short for currency.
So I just in the example when we format a number at the currency we get the dollar sign and
every
three digit is separated by coma and by default when we format a number as currency.
It's going to have two decimal point numbers.
If we don't want decimal point we can use C 0 or if we want one decimal point we can see
one.
Here is a list of common format specifiers in C-sharp.
So C for currency D for decimal E for exponential F for fixed point an X for hexadecimal.
All right.
Now let's flip over to Visual Studio and let's see all these concepts in action
Are right let's take a look at some of these useful string methods.
So here I've got a variable full name with my name and I know that there is a whitespace
character at
the end of this string.
So first let's take a look at the tree method.
Trim gets rid of the whitespace at the beginning or at the end of a string.
So cancel the right line.
I'm going to use a format string here.
So two single quotes and I'm going to put a placeholder here.
The reason for that is because I want to enclose my string with single quotes so we can see
the effect
of tree method.
Now let's apply some value here.
So full name that trim.
OK let's run the application.
Note that the whitespace at the end of my name is gone.
So this is very important when we receive input from the user.
Sometimes we need to trimming a string before doing processing on that.
Otherwise if we're going to compare that string with another string comparison is not going to
work
.
All right let's take a look at the two other method.
So I'm going to duplicate this line and change the label to of her.
Note that here we can chain these methods because each of these methods on the string class
return a
new string.
They do not modify the original string.
And that's what I meant by strings being immutable.
So Dot to upper less around application.
There we go.
Now let's say we want to break this string into first name and last name.
How do we do that.
There are a couple of different ways.
One way is to look for the index of this space and based on that split that string into two
parts.
So let's try that first.
So full name dot index of we can supply a character or a string here.
So I'm going to use a whitespace character now based on this index.
We want to split the string so we can declare first name as full name but substring.
Now this method has two overloads.
Look the first one takes only an index which is the starting index.
So it starts from that index and goes to the end of the string.
The second overload here takes a start index and a length that is a number of characters to
include
.
So I'm going to use this overload to take the first name.
What is my starting index at zero.
The beginning of the string.
How many characters do we want up to the index of space.
So that's going to be index and last name.
Now this time I'm going to use the first overload.
So I want to start from index plus 1 all the way to the end of the string.
Let's put these on the console
.
OK.
They go.
So first name Marsh and last name Ramadani.
Now there is an easier way to achieve the same thing and that's using the split method.
So if we'd call split we can supply a character or a string here.
So if I supply a whitespace character here.
Look what we get in the result the return type of this method as a string array.
So I store the result in a variable called names.
So if I hover my mouse over var look it's a string array.
Now I can easily get the first name
as names of 0 and last name.
It's going to be names of one.
Let's run the application.
They go.
We got the exact same result.
So if we're working in scenarios where we want to split strings this method is easier to work
with
.
Otherwise if we have some more complex processing we can use the index of an substring
methods.
Now let's take a look at the replace method.
Let's say we want to replace my name here Marsh with my actual first name which is
Marshlack.
So full name dot replace Marsh with Launchbury again here we can supply a character or a
string.
For example we can say Let me show we another example
we can say replace lowercase o with uppercase O or we can say replace whitespace with
nothing with
an empty character.
And this is exactly the effect of applying the tree method.
OK.
Now the important thing to remember is as I told we before all this method calls return new
strings
.
So the original string is not effective.
So let me get rid of these two lines here and display this
on a console run application.
Look washrag Ramadani.
Now let's take a look at a couple of useful methods to work with empty strings or not.
So in real world applications sometimes when we get input from the user we want to see if
the user
actually put a value there or not.
For example imagine we're building a form and the user is supposed to supply a credit card
number we
want to make sure that the user didn't enter a credit card number.
So how do we validate that.
Let me show we.
So look if string is now are empty.
So this is a static method on the string class and it takes a parameter I can supply null here
and here will display an invalid message.
So what do we think is the output of this program.
We should get the invalid message because wer have passed.
Now that's an argument.
So let's just verify that before we go to the next step.
OK we got the invalid message here.
Now what if I put an empty string.
We should still get the invalid message.
Look it's here.
So far so good.
But what if the user just enters space like this.
Technically this is invalid.
This is not a valid credit card number.
So this is equivalent to a user not providing any numbers at all.
Let's run the application.
Look we no longer see the invalid message here.
So this method was one of the first methods that Microsoft put in my framework.
So to work around this problem what we had to do was trim the string first
and then pass it to is now or empty method.
Let's run the application OK.
We see the invalid message now but this is a little bit tedious and ugly.
That's why in later versions Microsoft introduced a new method is null or whitespace.
No we no longer have to trim.
So if the string is empty or whitespace or not are we going to get the invalid message.
There we go.
And before we finish this lecture Let me show we how to convert numbers to strings and vice
versa.
So let's say we receive a number from the user.
And if we're building web or desktop or mobile applications always these inputs come as a
string.
So we going to convert that to a number.
Let's say we get an input which is the user's age let's say 25.
So we need to convert this string representation of number 25 into an actual number.
There are two ways to do this.
One way is to use the converse class.
This class has a number of methods and they all start with to like two in 32 to 64 to double
the decimal
to date time to char to buy it to bully and so on.
So in this case if we want to convert this SDR to let's say an integer I would use convert to
and 32
now integer is 4 bytes and we only need one byte to store someone's age because no one can
be older
than 200 50 years old.
So then we can change these two
to bite and then we can store the result here
and display it on the console.
Now let's take a look at the other situation.
We have a number we want to convert it to a string.
So let's say we've got it price here and that is twenty nine ninety five dollars.
We want to convert this to a string.
We can use price dot to a string.
So every object in dot net has a two string method.
The reason for that is beyond the scope of this course and that's something that I have
covered in my
C-Sharp intermediate course for now just remember this two string method is available
everywhere.
Now we can call this method without any argument which simply returns a string
representation of this
number.
But I want to format this as currency.
So I supply a format string.
So here in the intellisense Luque capital C is currency and by default it has two digits after
decimal
point.
If we don't want decimal point we can use see 0 or if we want one number after decimal point
we
can use see one.
So let's just convert this to currency and display the result on the console.
OK.
So
there we go.
Twenty nine ninety five and we get the dollar sign.
Now let's get rid of the decimal points.
So I put 0.
So it rounded that $230.
OK.
That brings us to the end of this lecture.
I hope we enjoy it.
And thank we for watching.
OK in this lecture we're going to work on an interesting problem summarizing text we have
seen on a
lot of blogs on our home page.
There is a list of blog posts and below each post.
There is a summary and at the end of the summary we see dot dot dot.
How do we do that.
So let's start by declaring a variable.
This is going to be a really really really really really long text.
And we want to summarize it.
The first thing we want to do here is to check if the length of the sentence is below the
threshold
.
If that's the case we simply display it.
Otherwise we need to summarize it.
So if sentence length is less than 20 just an arbitrary number we simply displayed it.
Otherwise we need to summarize the text.
Now the first thing I want to improve in this goal is to get rid of these 20 as a magic number.
I would like to express it it's a constant so constant integer maximum length.
This way we don't have to spread that 20 all over the code as a magic number and the code is
more expressive
now.
All right.
Now how do we summarize this the poor way of doing that is to use the substring method
like this.
So starting from index 0 and taking maximum length but here's the problem with this.
The problem is we make a cut of a wart as a result of that kind of substring and that's not a
good
thing.
We want the summary to look clean.
So we want to take into account the word boundaries so the algorithm we are going to work
on here is
to count a number of words that roughly fits around 20 characters.
How do we do that.
The first thing we want to do is to break this sentence into words.
So
we use the Split method and we use the whitespace as a separator.
No we're going to have a string array of words.
Note that word is a String array.
Now we can iterate over this sorry for each word.
We count the length of that word.
Add them all together.
If we roughly get around 20 or Exit 20 that's a boundary where we need to cut.
So I'm going to declare a variable here called Total characters straight to 0.
Now we're going to loop over the words.
So as simple for each block for each word.
We need to get its length and we need to add it to total characters so total characters plus
equals
for that length.
And we also need to add one because of the space after that word.
Now if the characters exceeds 20 that's the time to get out of the loop.
So.
So immediately break now one more thing we need here is a list to dynamically store all
these words
that are going to be part of the summary.
So
in summary words it's going to be a list of string.
We'll learn about lists in the section about arrays and lists so a list is a data structure similar
to array where we can store a number of objects of similar type but the size is dynamic.
So now in the loop we need to add the kind word to our list then we do our checking to see if
the total
number of characters exceeds max length and we break.
So once we get out of this for each loop are some of the words list as all the words that need
to go
in the summary what we need to do is to create a string and join all these words using
whitespace.
How do we do that.
The string class has a method called join the first argument is a separator.
So the use of whitespace.
And we can pass our summary words Lescure.
Now this joint method returns are summary string Albany to do is to append dot dot dot at the
end.
And that's going to be summary that's displayed on the console
and run the application
note that we didn't cut off a wart
now in a real world application it would be nice to extract all this logic here into a separate
method
or a separate function so we can reuse in different places.
So what I'm going to do now is create a new method here.
So this is the end of our main method.
We can create another method here and that method has to be static because our main method
is static
.
So in order for us to call that method from the main method we need to declare it as static so
static
the return type of that method should be a string.
Let's call it summerize text.
That takes a parameter of type string it text like that.
And I'm going to move all this logic here.
The only problem is we use the word sentence before.
Now we use text so we can replace 10.
So we need to replace it with resharpen is pretty easy.
Altan enter change all sentence to text.
If we don't have resharpen we need to manually go through each of these and modify them.
Now at the end instead of displaying on the console we need to return it.
So return summary.
And also we need to modify this one here.
So if the text is short enough we don't need to summarize it.
We just return it.
Now resharpen is telling me that we don't need this ELSE block here the else keyword
because it's great
out because if the text is more than max length obviously the rest of this method is going to
execute
.
So we don't need to explicitly use else here so we can clean up the code like that.
I like all of that shift and tab to format it can make this code even cleaner because it's obvious
that
this method is returning a summary text so we don't need to store this result in a variable and
return
it.
We can simply put this expression here.
In other thing we can do here is to have a second parameter here that specifies max length.
So instead of hard coding the number 20 we give this option to the caller of this method to
specify
the max length.
This way we increase re-usability so int max length and we can give we the default value of
20 in case
the caller of this method does not want to set the max length and we get rid of this constant
integer
.
And finally back to our main method
we can create another variable called summary call our summerise takes method and pass that
long sentence
here then displayed on the console.
Let's run the application.
We got the same result.
Now we can go and change the max lengths here.
So let's say a max length is going to be 25.
Let's see what happens.
So we got one more word in the summary.
Again we're not cutting off text in the middle of a word.
All we have a clean reusable method that we can use in different places.
And one last thing I would like to do here to improve the reusability of this method is instead
of declaring
that inside this program I want to put it in a class that I can use in different programs because
in
the real world applications we're not going to write all of our code inside the Program class.
We're going to have different classes for different reasons.
So let's add a new class to this project.
I had class lets call it string utility
and now we go back to program here we select this method which I use in our prayer.
We use controlled w to quickly select a block of text like this.
Is much faster than rolling down the shift and using the down arrow like that.
So control w and we can extend wer selection like that or control shift w.
We can reduce the selection cut Norbeck control and tab with which we know and here drop
it.
And finally we need to make this class public.
As I explained in the beginning of this course we're going to just work with public classes
and public
methods in discourse public is an access modifier.
And I'm going to explain access modifiers in more detail in the second part of this course
called C-Sharp
intermediate and of course we need to make this method public as well.
Otherwise it's not going to be accessible.
Let me show we.
So if we go back to a program and now we need to change to summarize takes two string
utility dot c
see there is nothing there because we didn't declare the method as public.
So a control tab back here at the public here.
Back to the program.
Now if we put it here we see that utility method.
All right.
That brings us to the end of this lecture.
I hope we enjoy it.
And thank we for watching
So earlier in the course we'll learn that the String class is immutable which means once we
create
a string object we cannot change its content.
If we're dealing with situations where we have a lot of string manipulation operations we can
use
a string builder string builder as a class that is defined in the system that takes namespace and
represents
immutable string and makes it really easy and fast to create a string and modified on the fly.
But unlike the String class it's not optimized for searching.
So it doesn't give we methods like Index of last index of contains starts with we know all
these strings
searching operations.
Instead it provides a number of useful methods for manipulating strings like append to add
something
to the end of a string insert to add something at the given index remove to remove something
from the
string replace to replace a character or a string and clear.
Let's flip over to Visual Studio and see stream builder in action
Are right in this we are going to have some fun with the string builder.
So let's create an object of type string builder Let's call it builder district builder.
Know that as I typed News Stream builder resharpen automatically added using system to
text on the top
.
If we don't have the sharper.
Obviously we have to add that namespace werself.
Now let's explore some of the methods of string builder so builder.
We have 3 append methods.
Append append format and append line.
Are going to go through each of them.
Let's take a look at the pan method.
This method has a few different overlooks one that takes bool and other one takes byte one
takes character
one takes character and repeats that and one that takes a character array.
Let's use the one that is currently highlighted here.
So I would like to have this dash character repeated ten times now as displayed on the
console.
So that's what we got.
Now let's have a newline here so we can use appendline length.
And after that we can use append again and display some header.
Let's call it Heller.
We can have another newline.
And finally we can have those dashes again.
Let's run the application.
So see we easily created something like that.
Gneisenau is about creating something that looks good.
It's about manipulation of strings.
Like earlier in the course we had a lecture on the random class and there I showed we how
we can create
a random string like a random password in that lecture.
I showed we how to use a character or a two story wer random characters.
Now that we learn about string builder we can use a stream builder to generate random
sequence of
characters.
Let's look at other methods so we can't say replace all these dashes with the plus side.
Let's look at the result.
They go very easy
or we can call it remove and say start from index zero and remove 10 characters.
Let's see what happens.
So the line on the top is gone.
Or we can use the insert method with insert but need to specify an index so we can pass 0
here to put
something at the beginning of this string.
And as the second argument we can't pass anything we can't create a new string here and use
this overload
here.
Specify a character and account so dash and
antenne we're going to repeat that 10 times.
So basically with that we are going to add a line of those dashes at the beginning of our string
builder
.
Let's look at the result.
There we go.
So we see string builder makes it really easy to modify strings and also it's faster than using a
string
and using its manipulation operations because those stream articulation operations like
replace insert
remove all these methods create a new String object into memory and return that.
Now if we have a large number of stream manipulation operations that extra creation of
strings and
be a little bit costly so we can use a string builder.
And this way wer program is going to be even more efficient.
Also note that when we create a stream builder we can also specify a starting string.
So let's set it to Hello World and then we can do all these other manipulations after.
Let's look at the result.
Now interestingly after all these manipulations the first part of hello world is removed then
only deal
is left and the rest is replaced by some dashes.
So $3 is really easy for manipulating strings.
But what we need to remember here is that with string builder we're not going to get string
searching
methods.
So.
Builder Daut.
See.
These are all about manipulation.
We don't have any methods to search for the index of a character or a string inside that string
builder
.
And one last thing is we can use an indexer
to access individual characters in the string builder.
Just like how we do with a string.
So if I want to display the first character
I just use the next year
and let me add a label here
and run the application.
There we go.
There is character.
And one last thing I want to show we here is actually very interesting look at the signature of
the
append method that returns a string builder.
It's not a void method.
It returns a string builder which means we can chain these append methods altogether and
make our code
cleaner.
So this append method returns our builder with the update of string and then right after that
we can't
call this second apan method.
And again this append line returns the optative string with a newline.
Now we can append the rest to it.
We need to get rid of semicolon here.
Same here same here and chained them together.
This makes the code less noisy and more readable and the same is true for other methods here
like replace
remove insert.
All these return a string builder.
So again I can go here
and chain all these methods
just like that.
So the code is much nicer and much cleaner.
So does pretty much all about string Miller.
I hope we enjoy this lecture and thank we for watching.
A.S. I'm going to teach we how to work with files and directories in C-sharp.
And as part of this I'm going to introduce we to a few useful classes in Dattner file file info
directory
directory info and path.
So let's get started.
OK in this section I'm going to talk about how to work with files and directories and C-Sharp
in dot
net.
We have a namespace called system that I O and that's where all these classes do work with
files and
directories are located.
There are many classes in this namespace and it's really impossible for me to go through all
of them
.
First of all it's going to take a lot of time and honestly I don't have the knowledge of every
single
one of them.
In fact I don't think there is anyone on this planet who knows every single class in darkness
framework
.
So we will discover classes based on wer needs.
But in this lecture I'm going to introduce we to a few very common classes that we may find
useful
in wer programs.
These classes include file and file info directory and directory info and path.
Let's see the difference between them so file and file info classes.
Both provide methods for creating copying deleting moving and opening files.
They have very similar interfaces.
The only difference is FileInfo provides instance methods where whereas file provides static
methods
.
So why do we need different classes for static or instance methods.
The difference is if we're going to have a small number of operations that say good attributes
about
the file it's more convenient to access the static methods of the file class.
But the problem with this static methods is every time we call it a static methods some
security checking
is done by the operating system to make sure that the current user has access to the file.
So if we're going to have a large number of operations this is going to affect the performance
of wer
application.
So in that case it's more efficient to create a filing for class and access all its instance methods
.
This way security check in is done only once during creation of a file object.
So here is a list of methods that are pretty useful to know about these classes.
Again this is not a complete list by any means.
My intention is to just give we an idea of what we can do with these classes.
So create Mithu is of course used to create a file.
We also have copy delete exists to check if a file exists.
Get the attributes which returns the attributes of the given file or move to move the file
around or
read all text which reads all the text in a file directory and directory info are very similar to
file
and file info so directory class provide static methods whereas directory info provides
instance methods
and we use either of these classes to work with directories.
Here are some useful methods.
Create directory delete exists.
Get current directory which returns where the application is currently sitting.
Get files which returns the files in wer directory and in that method we can provide filters.
For example we can say Give me all files or files with a JPT extension.
We also have move and get logical drives which returns the logical drives of wer hard disk
like C drive
D drive and so on.
We also have the path class which provides methods to work with a string that contains a file
or directory
path information.
And here are some useful methods of the path class directory name get filename good
extension which
is very useful.
Let's say we have a path and we want to get only the extension of that path so we don't want
to processor's
string werself.
We just want to get the extension.
So we simply call path God get extension and provide wer string there.
We also have a temp path which returns the path of the current users temporary folder in the
next few
lectures.
We're going to see demos of these classes in action
OK this video I'm going to show we how to work with file and filing for classes.
These classes are very similar and they both provide methods to work that files.
The only difference is file provides static methods where as file info provides instance
methods.
So let's take a look at file look here are the static methods of the file class.
We can copy a file create a file decrypt an encrypted file deleted encrypted check if it exists
and
see there are lots of methods here.
It's really impossible for me to go through all of these methods.
I'm just going to show we a few of them in this lecture.
So we will have an idea of how to use them then we can go and use the other methods
depending on wer
needs.
So let's take a look at copy.
This method takes two parameters.
They both are a string.
The first one is the source filename.
So let's say we would like to copy a file that is located in the C-Drive in the folder temp and
it's
called my file that JPT.
And the second parameter is the destination file it read the tooltip.
It says this cannot be a directory or an existing file.
So let's say we would like to copy these to the drive in the same folder and call it my file that
JPT
.
This method has two overloads.
The second overload takes a parameter of type Boolean which we can use to indicate that if
the file
exists or we can override it.
Now first thing I want to do here to clean up this code is get rid of all these double
backslashes.
So that's where we can use a verbatim string.
They seem to put an answer on here and get rid of all these noisy backslashes
.
That's it.
Let's take a look at the delete method.
Again this method takes a path.
So what I'm going to do I'm going to declare a variable here called pathic so we can reuse it
in different
methods
.
Just like that we can check if a file exists on a disk.
So if the file that exists this method again takes a pass and returns a boolean
then we can do something about it.
And finally if we want to read all the text in a file we can use file but read all text.
This method returns a string or if we want to read a file as binary we can call read all bytes
which
returns a byte all.
So let's try this one again this method takes a path and returns a string.
So we call it content.
Now let's take a look at the equivalent methods in the filing for class.
So we the file info.
First we need to create an object.
And of course we need to specify a path here
and then if we want to copy this file we can call copy to method and this method takes a
parameter
of type string called destination file name.
Again we can apply whatever here.
I know that this method also has an overload which takes a second parameter called bool
overwrite.
Similar to the other method.
I'm going to leave it for now.
Or if we want to delineate finding info that delete takes no parameters to check if the file
exists
.
Filing folder exists which in this case is not a method it's a property.
So if file info that exists then can do something about it.
And finally note that filing for does not have a read all text method.
It's only available as a static method in the file class with the file info.
We need to call the open read which returns a file stream but the stream is a different way of
reading
a file.
And personally I'm not a fan of that because it's just a little bit complex.
Later in the section I will show we a very simple way to read the file.
If we don't want to use file that read all text but the bottom line here is note that both these
classes
are very similar in terms of usage.
The only difference is by providing static methods where as info provides instance methods.
So if we want to execute a small number of operations against a specific file it's more
convenient
to use these static methods so we're going to have to create a new file in file object.
But with this static method every time we call them the operating system does some security
checking
and that can affect the performance of re-application.
If we have a large number of operations in that case it's more efficient to create a filing for
object
and call the instance methods on that object.
That's it for this lecture.
I hope we enjoy it and thank we for watching.
OK in this video I'm going to show we how to work with directory and directory info classes
again to
keep it practical.
I'm only going to demonstrate a few of common and useful methods in these classes so we
get an idea
of how to use this classes.
Then I will point we to the MSD and documentation so we can look at the other methods
available in
these classes.
In case we need to know about them.
So similar to file and file info directory and directory info provide static and instance
methods.
Let's take a look at directory so directory that create directory and this method takes a path so
we
can use a verbatim string here.
Say C-Drive in Tampa folder one as easy as that if we want to get the files in a given
directory we
use directory that get files.
This method has three overloads.
The first one takes a path.
The second one takes a path and a search pattern so we can filter and say give me all the files
with
the JP G extension and the third overload of this method takes a parameter of type search
option which
is an enumeration.
So as an example C-Drive projects C-Sharp fundamentals.
Let's take a look at all files.
So that's my search pattern.
And now I'm going to use search option that all directories.
So this method returns all files in the current directory and it's up directories.
Let me show we the return type of this method to remove the practices and open it again.
Look at the return value as a string array.
So we can use a For Each loop to iterate over the.
So I can store the results in a variable called files
and then do it for each
and display the result on the console.
Let's run the application.
So we see it's returning all files in every directory and every subdirectory starting from C
drive
projects to our fundamentals.
It can change the filter here to say show me only s l n which is visual studio solution files but
take
a look.
So we see I've got a small number of solutions here.
Now let me show we another example.
This time I'm going to call get directory's.
So it returns only the directories inside this path here.
So projects C-Sharp fundamentals
and specify search options that all directories.
So we get all directories recursively.
Now this use a for each loop here.
And this platers off on the console
.
I'm going to comment on these few lines so we can see the difference.
So note that now it's returning only to directories
if we want to see if a directory exist or not.
We simply call directory thought exists and here we specify the path.
So we see all these methods are pretty simple and we don't need me to go through each of
them and
waste wer time.
We can learn about them werself.
The only thing I want to show we in this lecture is the difference between directory and
directories
for using Xacto like file and filing for.
So I'm going to show we one example.
I create a new directory info specify a path here whatever.
And now if I want to get all files or all directories inside this directory object simply directory
info that get files or get directories.
So this method is exactly like the other method.
It takes a search pattern on an enumeration called search option.
Now that's pretty much all I wanted to show we about directory and directory info.
If we want to learn about individual methods in the file file in full directory and directory in
for
classes simply go to Google and search for say file info class C-Sharp then pretty much in all
cases
.
The very first link and Google is the documentation for that class on MSD n Microsoft
Developer Network
.
So let's go here.
So here is the official documentation of filing for class.
Can scroll down and look at each of these properties and their description.
Same for the methods all here with their description.
Let's take a look at one of them here.
Let's say encrypt.
Now scroll down here and look.
There is already an example for we here.
So it's not rocket science.
We can easily figure it out on wer own.
I hope we enjoy this lecture and thank we for watching
So in a fiction we learned about different classes in .net to work with files and directories.
These classes come in pairs like file and file info files per wise static methods.
Whereas filing for provides instance methods which one do we use depends on the number of
operations
.
If we have small number of operations it's easier to use the File class because we don't have
to create
a new object.
But remember every time we access a file there is some security checking done by the
operating system
.
And if we have a large number of operations it's going to be costly.
So it's more efficient to use the file info class.
In those cases and the same applies to directory and directory.
And remember if we need to access individual parts of a path like the extension filename
directory
name it's easier to use the path class as opposed to string searching methods in the String
class.
I hope we enjoyed this section and I will see we in the
A.S. I'm going to show we a few techniques to debug wer applications I'm going to show we
how to
use breakpoints watchers Carlstadt locals and those windows.
I'm also going to talk about some good programming practices such as defensive
programming.
So let's get started.
One thing that distinguishes a good programmer from an average one is that a good
programmer often thinks
of cases.
What they mean when each case is uncommon scenarios an average programmer often
assumes the end user
enters values into the forms the way the programmer expects but the reality is different.
So back in the example from The Last Lecture look at the first line here we have a list of six
numbers
and in the second line we want to get the three smallest numbers in this list.
What if we only have 2 numbers in our list.
So I'm going to remove these four numbers and run the application
the application blew up we got an exception.
So close the program we got argument out of range exception and Index was out of range.
So what's going on here.
When we face situations like this that's when we start debugging.
So I want to run the application into debug mode and find where in the code we're getting this
exception
what line.
So remember our shortcut and five to run application in the debug mode control at 5 to run
the application
without debug mode.
So I press 5 now.
OK we start at this break point.
I want to continue execution.
So in the last lecture we learned about step over step into and step out there is one more way
to continue
execution.
And that is continue to build the next breakpoint.
So I can press F5 again.
A look now we are at our second breakpoint.
So so far everything seems to be fine.
We didn't get an exception.
So let's continue.
If I have one more time.
OK we're back on this line again one more time.
Mm hmm.
I don't seem to be right.
We know what I want to get rid of all these breakpoints and just run the application and see
where
exactly blows up.
So this is something that often comes up when we're building big applications.
We put various breakpoints here and there and once we fix the bugs we forget to remove
them.
And then these break points getting the way.
So how do we find them and how do we remove them.
We go to debug.
One way is to go straight here and click delete all breakpoints or disable all break points.
That's the quick way.
There is also another way we can go to Windows
and breakpoints.
So here we see all the breakpoints in the application what file what line what character can
DoubleClick
go there.
We can disable them or enable them or we can delete them.
So I'm going to delete both of these.
Now I want to restrict application.
The shortcut is control shift and F5.
If we ever forget these shortcuts we can always find them.
Just go to the Debug menu here.
So look we've got continue which is a five step debugging which is shift and a five.
I know I'm looking for restart which is control shift and F5 so restart application.
OK this is where it blew up.
So I put a breakpoint here as my starting point f nine.
Now let's look at the exception argument.
Out-of-range.
So what's happening.
Let's close this.
Look at this list.
This list is empty.
There are no elements here yet.
We are assuming mean is the first element in the list.
So this code is not really reliable and this is one of those areas that separates an average
programmer
from a good programmer.
Now before we fix this bug Let's see why is this less empty.
If we remember this line the purpose of this was to remove the smallest number from the list
and we
continue repeating these until we get enough small numbers based on the value of count here.
So as we're removing these numbers from the list at some point the list becomes empty.
In this case because our list originally had 2 numbers in it after two eiter patients the list
became
empty.
And that's why we get this exception.
Now the question is how do we fix this but we have a few different ways here.
One way is to have an IF block in the Gets smallest method that checks if the count that we
pass here
is greater than the number of elements in the list.
The reason we're getting this exception is in this case we want three small numbers.
What the list is only 2.
So this is one way to solve this problem.
Another way is to put it conditional in get smallest method.
So we need to check that if the list is empty.
So if the list is empty what should we do.
Should we return 0.
I don't think so.
Imagine if our original list.
I mean this list here had a number of negative numbers that at some point we get here the list
is empty
.
And Bridger's zero.
So the program end up displaying zero as one of the smallest numbers in the list which did
not exist
in the list in the first place.
Another option is to check if the list is empty here.
Throw one exception.
So that's one of the conditions or criteria for this method to do its job.
This is what we call defensive programming.
So when we get input here before doing any processing we want to make sure that the input
satisfies
some criteria.
If not we are not going to continue processing.
Now there is a third way here.
Can we see that.
It's not quite obvious but yet is very important.
Look at this method get smallest.
This method has a side effect.
So this original list that was sent here we are continuously removing some numbers from it in
order
to calculate the smallest numbers and side effects are not good.
They make wer methods unreliable and they're often hard to find bugs that are because of
side effects
.
Now for a second I want to stop the debugger here.
I'm going to put those four numbers back here.
So if we're on the application now everything works OK.
We got one two three but let's iterate over the original list.
So I'm going to change these two numbers.
Look at the result.
Our original list is changed one to three is removed there.
And this is what I meant by side effect.
So in my opinion that's a more serious problem that we need to address first.
Now that may or may not solve the bug that I introduce at the beginning of this lecture that's
fine
.
If it doesn't fix it we're going to continue debugging and find a right way to fix that bug.
So the first thing I want to do here is to remove the side effect.
How do we do that.
So in the good smallest method instead of removing these numbers from the original list I
want to create
a copy of this list to do my processing.
So
I call this less buffer so we create a new list and pass that original list here and then instead of
removing these numbers from the original list I remove them from the buffer.
And one more change here we need to change this list to buffer.
So now look this list the original list is only used during the creation of the buffer.
Now let's run the application
OK.
Beautiful.
The original list is not a.
So we removed the side effect.
Now let's get back to the original bug that I introduced at the beginning of this lecture.
So I'm going to remove
these four numbers and change the foreach block to look at the smallest numbers.
Let's run application.
OK we still have a problem here.
So in the next lecture I'm going to show we how to fix this problem.
OK back here we want to fix the book from The Last Lecture.
So we have a list of two numbers and we want to get three the smallest numbers in this list.
And as we remember from the debugging session in the last lecture this problem happened.
And this line here.
So at some point the input list that we give to this method becomes empty and we try to find
the minimum
number in an empty list.
Well we have two choices to fix this problem.
We can put a conditional statement here and make sure the list is not empty.
That's one way the other way is to have a conditional statement.
In this method here.
So we want to make sure that count that we get here is not greater than the number of
elements in this
list.
Now both these solutions might sound reasonable but which one do we think is a better
solution.
I think a better solution at this point is to check if count is not greater than the number of
elements
in this list.
Why.
Because we're asking a question in this method.
But the question itself has a problem.
If the question is meaningless we can not get an answer.
Let me use a metaphor.
Imagine we ask wer friend.
Do we eat with a pen and paper doesn't make sense.
The question should be do we eat with a spoon or fork or with chopsticks.
So when the question is meaningless we cannot provide an answer.
So in this case I'm going to attack this problem by making sure this method gets smallest gets
the right
arguments as the question.
Now
so I'm checking if count is greater than the number of elements in this list.
Then we throw an exception exception of type argument out of range exception.
This is a useful technique in defensive programming so we check the input first before doing
any processing
.
Now one more thing I would like to add here we can have a message here.
Count cannot be greater than the number of elements in the list.
Let's run the application now.
The application crashed again.
So have to solve the problem.
Yes we did solve a part of the problem.
Now we might ask Marsh how is this better than before because before we got an exception
anyway.
Let's see the difference re the exception argument out of range exception count cannot be
greater than
the number of elements in the list.
So this exception is more meaningful is telling me why the program crashed so when it
comes to troubleshooting
I would have a better idea of what's happening here.
I would know that the client of this method in this case this line here is sending the wrong
data.
Let me temporarily comment out these two lines here and run the application again.
Read the error now index was out of range.
Must be non-negative and less than the size of the collection.
This error message is too low level and is coming up from a method.
Further down in the list of method calls so it came from this method here.
The important thing to consider here is we should not get here in the first place.
The program should stop execution at this point and that's why we added this.
If block.
Here the reason I add this here is not just to display a more meaningful message is to prevent
wer
application from going in the wrong state.
Now this is a very simple program but imagine if this was a big real world application with a
database
.
If wer application goes in the wrong state there is a chance that sometimes that state is
persisted
in the database and the next time we load a page we show some data to the user that makes no
sense
and in situations like that we're going to have a hard day finding that bug.
We can spend a day or two maybe even a week to figure out what was happening.
OK back to the business here.
Now we solve this problem with this count being greater than the number of elements in the
list.
What do we count as 0.
Do we think it's a valid question.
Give me zero smallest numbers.
No it's a ridiculous question.
What if it was minus one.
It just doesn't make sense.
So we need to change this slightly to something like.
So if count is greater than the number of elements in the list or is smaller than or equal to
zero.
That's out of range.
Of course we need to change this message slightly
.
Counts should be between 1 and the number of elements in the list.
Let's run the application.
OK we got this meaningful exception here because we passed minus one to this method.
Now to further expand this topic of defensive programming.
What if we send an empty list here.
Something like this.
We might say OK Marsh we can do another check here to make sure that the list is not
empty.
We can certainly do that but in this case I can show we that the existing logic would work for
an empty
list.
Why.
Because first of all I know we cannot send minus 1 or 0 here so we need to send one and
because one
is greater than the number of elements in the list.
This logic will stop the program execution so there is no need to write.
If list that count is 0.
Throw an exception is just redundant.
But what if the list was null.
What if I send null here then I'm going to get another low level exception.
Further down the track.
So let's investigate that run application.
The famous null reference exception object reference not set to an instance of an object.
So this is something that I would like to prevent.
At the beginning of this method to make sure the question is the right question
.
So if list is null we throw an argument not exception.
OK so in this lecture we covered some of the cases around this algorithm and we improved
the reliability
of our code.
And that brings us to the end of this lecture over the next couple of lectures.
I'm going to show we more debugging tools in Visual Studio.
I hope we enjoyed this lecture and thank we for watching.
OK back here I changed the declaration of our list back to what it used to be.
So numbers 1 2 6 and also added.
Number three here.
So we get three smallest numbers in this list.
Note that we have one breakpoint here.
Now I'm going to run the application in the debug mode.
So 5 so we are here.
Now this is a very simple application with only three methods but often a real world
application consists
of tens hundreds or even thousands of classes with a few methods.
So sometimes when we're debugging we might get lost.
Now I'm going to introduce we to a window that shows we how we got here.
This window is called call stack so we can find it in debug windows call stack.
So this window shows the order of methods that were called from the moment that the
application ran
up to where we are now the item on top of this list is wer current location and the item on the
bottom
of this list is where we started.
So we can double click here.
That brings me here.
Let me dock this window.
I don't like this one.
So before we jumped into this method this is where we were.
Now I double click main and this is how we started.
So we went to this method and then ended up here.
And finally in get smallest method.
So if we get lost.
Remember the call stack window
WHATS NEXT
So we made it this far.
I hope we have enjoyed this course.
Now this course is the first part of my three part C-Sharp course over the next part which is
called
C-Sharp intermediating.
We'll take a closer look at C-Sharp classes.
I'm also going to talk about a very important topic that a lot of C-Sharp developers struggle
with and
that is called interface's.
I'm also going to introduce we to object oriented programming.
I'm going to talk about encapsulation inheritance and polymorphism.
So I hope to see we in the next course.
And remember we can find coupons for my other courses at the end of this course.
So have a great day and I hope to see a
INTERMEDIATE
No that object orientation is a complex topic and it takes a lot of books videos and years of
thinking
to really -- but this course opens wer eyes to the object orientation.
We learn the principles of object orientation including encapsulation inheritance and
polymorphism
.
I will show we why encapsulation is so important and how it helps writing robust code.
I'll talk about inheritance inheritance is a way to reuse code but unfortunately it's misused a
lot
by a lot of amateur designers and developers.
I will show we the problems with inheritance and then I'll introduce we to the concept of
composition
as a more flexible way to reuse code.
Then all talk about polymorphism.
I will show we how we can take a piece of code that has a lot of if else and switch statements
and
refactoring it into an object oriented style.
We learn how we can change the behavior of an application by extending it.
So instead of changing the existing code which may affect parts of wer application we create
new classes
that change the behavior of wer application.
And this is extremely powerful.
And finally I'll talk about interfaces.
Unfortunately there is a lot of wrong information about interfaces in the community.
In fact when I started learning C-Sharp back in 2002 the book I read which was actually
published by
Microsoft gave me the wrong information about interfaces.
And for that reason I was confused about interfaces.
For years I was taught that interfaces are used to implement multiple inheritance in C-sharp
and that
is absolutely wrong.
It took me years to really understand interfaces and that's the reason I decided to create this
course
for we.
So whether we're brand new to the concept of classes interfaces and object oriented
programming or
we have some experience we're going to get a lot out of this course.
I will show we how it interfaces improve the testability and extensibility of wer application
so we'll
see an introduction to unit testing and how we can use interfaces to improve the testability of
our
application.
I've been really excited about making this course and I hope we'll become a better developer
after
watching this course.
That's enough introduction for now.
Let's get started.
OK object initializers in the last lecture we learned about constructor's we know that we use a
constructor
to initialize an object and put it in an early state in C-sharp.
There is also another way to initialize an object and that is using an object initializer an object
initializer is simply a syntax or quickly initializing an object without the need to call one of
its
constructors.
Well we do need that simply to avoid creating multiple constructors.
Let me show we an example.
Imagine we have this person class with a bunch of fields.
Now this is a very simple example.
We only have four fields here.
In the real world application.
We might have a few more fields.
Now with this class if we want to create constructors for initializing various fields we may
end up
with a class like this.
So as we see here I have four constructors.
The first one takes only an ID.
The second one takes an idea and a first name.
The third one takes an idea with first name or last name and so on.
So we see there are so many different combinations and this is what we used to do in C-sharp
before
object initializers were introduced.
So as we seeing writing code like that is messy and easily becomes out of control.
So object initializer came to solve his problem with an object initializer.
We don't need any of these constructors.
We can't simply initialize a person object like this.
No these curly braces here.
I'm not calling one of the constructors of the Person class.
The syntax we see here is what we call object initialization syntax.
So basically we specify the name of properties and assign them some initial value.
Note that behind the saying when to initialize an object like this the default or parameterless
constructor
is going to be called.
And then any properties we set here are going to be initialized.
So with this way we can reserve constructors for scenarios where we really need to use them.
As I explained in The Last Lecture.
So an object cannot behave without being passed some initial values.
That's pretty much what we need to know about object initialization syntax.
The next lecture.
We'll take a closer look at our methods and their parameters.
I hope we enjoy this lecture and thank we for watching.
OK access modifiers So far we have seen me declaring classes and their members with the
public key
word public is what we call an access modifier in C-sharp we have two ready five access
modifiers public
private protected internal and protected internal.
And this lecture I'm going to talk about public in private and we'll leave the rest to when we
get to
the lecture about inheritance.
So what is an access modifier and access modifier is a way to control access to a class and or
it's
members.
Now we may wonder why do we need to control access to a class or its members.
The reason is to create some kind of safety or guarding our applications to improve the
robustness in
the lecture about feels.
I explain how we can use the read only modifier to make sure that the field is assigned only
once.
And this way we developers will not accidentally create bugs in our code.
Take a look at this example here.
I have declared a customer class with a name field that is declared as private with this code.
When we declare an instance of the customer we cannot access the name field so we cannot
go John dot
name that will not compile.
Now we may wonder why do we need something like that.
Well that's the beginning of object oriented programming and object oriented programming
which is actually
one of my absolute favorite topics.
We have three major concepts encapsulation which is also referred to as information hiding
inheritance
and polymorphism.
In this lecture we're going to learn about encapsulation and throughout this course we'll see
more examples
of that encapsulation.
We're going to leave inheritance and polymorphism to the later section in this course.
Let's start with encapsulation.
I want to use an analogy think of a restaurant in a restaurant we have several roles.
We have a cashier we have a manager.
We have a chef.
We have one or more kitchen hands.
We have one or more waiters or waitresses and all these roles collaborate together to provide
an amazing
experience for we.
Well hopefully because sometimes we go to a restaurant and we come back very
disappointed.
But anyway think of the interaction between a waitress and a chef.
A waitress takes the order and passes it to the kitchen and the chef looks at the order and does
his
job and when he's ready it notifies the waitress so that chef is responsible for a few things
which
is outside the responsibility of the waitress the waitress is not going to go to the kitchen tell
the
chef how to chop the vegetables and how to cook the meat.
And I don't know about different spices.
Each of these roles are responsible for their own things.
They have some knowledge and some capabilities that perform some functions suffer should
be the same
in sulfur.
We don't have a chef or a waitress but we have classes and these classes collaborate to
perform the
functionality required from the application.
Now we want to design our classes such that each class is responsible for one thing it does
only one
job and does it perfectly.
We want our classes to hide some of the information about how they do the things they are
responsible
for.
We don't want other classes to know about the details of other classes.
And this is what we call encapsulation.
So we want to encapsulate some data in terms of fields as well as some behavior or
functionality in
terms of methods and classes.
And we want to hide the details from the outside.
So when it comes to fields we want to declare them as private and provide methods that
would give access
to these fields.
We call these methods getters and setters and these methods are going to be public.
So we think of fields as the implementation detail which should be invisible from the outside.
It's how a class store something in memory.
We don't want any other classes to know anything about that.
So to show we an example here we have a person class that has a name field that is declared
as private
.
So with this code if we create an instance of the person class we can access the name field of
that
object.
Instead we need to call one of the methods here said name or get any look at the set named
method here
.
The interesting thing about this method is that it does a check before assigning the name field
of the
person.
So if the value that is passed to this method and as the argument is null or empty it's not
going to
set the name field.
And this is one of the advantages of providing setters and getters.
We can know that we have the same thing with a field if field is purely storage in the
memory.
It doesn't have logic with a setter or a getter.
We can have some logic when accessing that field.
OK.
Before we start coding I just need to emphasize something here in terms of naming
convention in C-sharp
.
We have two naming conventions.
One is called Pasko case.
The other is called camel case with Pasko case.
The first letter of every word should be opera case.
Like the person here or name or certainly not that the first letter of every word is uppercase
with
camel case the first letter of only the first word is going to be lower case.
But the first letter of every word for that is going to be uppercase.
An example of camel case is the name parameter here.
So the first letter is lorikeets.
Now when it comes to classes we need to use the Pasko case when naming the class or any of
its methods
for fields.
The convention is to use the camel case prefix with an underline.
So we need to change the name field here to something like this.
So private fields should start with an underline and they should follow the camel case.
OK I think that's we know theory let's start coding and see all these concepts in action.
OK let's declare a class called person.
And know we can declare a field called birth date which should be of time day time but we
no longer
are going to declare a field as public.
Instead we're going to use private so private data time
Birthday.
No that I have used and I underline here and Kemel case.
So the first letter of the first word is Laura case.
Now with this code we cannot access to birth date field outside the person cause.
So if we go to the main method here and create a person object
person dot c we don't see the birth date field.
It's hidden from the outside.
And that's what we mean by information hiding in object oriented programming.
Ok then how do we set the birthdate for that to happen.
We need a method.
So many movies for now I can do a person class and define two methods.
Public void set birth date and this method takes a parameter of type day time and we call it
birthdate
.
At this point if there are any logics around birth date we can implement them here.
In this case we're going to keep things simple.
We don't necessarily need the logic or unbirthday that this point.
So what we need to do is simply set the birth date to the Valeo pass to this method
and we declare another method of like date time
get birth date and this method simply returns that birthday feel.
Now with these two methods we can go back to the main method here and say a person that
set birth date
we can say new date time 1982 1:1.
And of course we can read the birthdate.
So cancel that right.
Line person God get Versteeg.
We can run this application.
And we got the birth date on the con..
OK I know what we're thinking we probably are confused why we changed the axis modifier
for birthdate
to private but then gave two methods here that directly modify the field or return this value.
How is it different from directly going to that field.
Well if that's what we're thinking it's in fact a good question.
That's one of the questions.
I also have when I started with object oriented programming the answer is objects are about
behavior
about what they do their fields is primarily their internals their implementation detail which
should
be hidden from the outside world.
Even though in this example it doesn't really make a difference whether we have a public
field or a
private field with two methods.
But from an object oriented perspective we want to follow the principle of encapsulation
which suggests
that objects should hide their implementation detail and reveal what they can do as opposed
to how they
do what they're supposed to do.
We the examples always show we for this course we realize the importance of this concept
more and
more.
Well that's it for this lecture.
What I want we to take away from this lecture is we're going to declare our fields as private
and
the naming convention is under line and Kemel case in the real world applications we are not
going to
define two methods like the ones we see here.
This was purely for demonstration and because I want to take things in a step by step fashion
in the
next lecture I will show we an easier way to achieve the same functionality.
And that's what we call properties.
I hope we enjoyed this lecture and thank we for watching
OK we go to indexers.
What is an indexer.
A mixer is a way to access elements in a class that represents a list of values.
What do we mean by that.
Well let's take a look at a few examples.
We have all of the work by indexers.
Here are a couple of examples.
So here we have an array of integers and this is an indexer so we can access the first element
of an
array like this or here is a list a list of integers.
And again here using an indexer we can access the first element in this list.
Now we might say we all have the concept of lists and arrays and collections.
So we're not going to reinvent the wheel.
Why do we need to define an index or in our class.
Well sometimes we have classes that have collection semantics.
For example think of an HTTP cookie. An HTTP Cookie in case we're not familiar with that
is a file
that is sent from wer browser to the web server upon each request.
We have developers use a cookie to identify a user.
We can store some settings about the user in that cookie in the cookie.
We have a list of names and values.
So imagine in a project we have implemented the concept of A should to be cookie.
Now the code that consumes are AC to be cool typically class might look something like this.
So here we are creating an instance of the typical new class.
We set the expiry date.
And here is where we can use an indexer.
So it is a mixture.
I'm specifying that the name of the user is Marsh.
Done an indexer.
We have to write a method like that item here and pass a key value.
We'll see that achieving the same thing with an indexer is easier and requires less code.
If we want to get the value of a cookie item using an indexer.
Here is what the code would look like.
So we simply use the indexer has the key and we get the value without an indexer we have to
write a
method like get item.
Again the code that uses an indexer is easier and shorter.
Now in real work projects it's unlikely that we're going to create an be Kahu class because it's
already
part of darkness framework.
But I use this as an example in case we're working with a class that has the semantic of a list
or
a collection or a dictionary.
That's where we can improve wer code by using an indexer.
It's not something that we may see everyday in wer career but I want we to be aware of this
feature
.
Now how can we declare an indexer and indexer is nothing but a property.
So we can declare an indexer exactly like how we declare a property.
So we have the data type like string.
Then in sort of an identifier we use that this keyword.
And here is the index or notation.
So brackets and inside the bracket we have the type of indexer.
So in this case with the typical key I want to find items by the key which should be a string.
So my indexer here is a string and I give it the name of key.
The rest is exactly like declaring a property.
We have a get method and a set method.
And here rewrite the logic for accessing that particular element.
Let's start coding and see this in action.
OK.
We first start by creating an HTTP Cookie class
and the typical key.
Now I'm going to put this in a separate file.
I've already learned that before alt and enter enter.
OK now we need a field to store the key value pairs in the cookie that data type or the data
structure
we use for that is a dictionary.
If we're not familiar with a dictionary it's a data type that resize in system that collections that
generic and it uses a hash table to store data hash table has a special mechanism that makes it
extremely
fast to look up an item by its key.
So whenever we have a list of objects and we want to look them up by a key as opposed to an
index
we should use a dictionary if we have a list of objects and we would like to look them up an
index
and a list is a better choice.
OK now let me declare a dictionary private dictionary.
I want this dictionary to be of type string and string.
Now what this means is this is a generic class.
This is a generic class and these are generic parameters and these parameters specify the type
of the
dictionary.
So in this case I'm specifying that the keys should be of type string and their values should be
all
soft type string.
OK.
Now let's give it a name dictionary.
I like to initialize this in the constructor dictionary.
It calls new dictionary.
That's it.
Just want to recap what we learned earlier.
We could potentially go and initialize this field straight here and that's perfectly fine.
It's entirely up to we.
We can do it here or in the constructor.
Now back here.
OK.
Now we need an indexer.
Declaring an index is exactly like a property.
So what are we going to do.
Is the public the return type string because we have key value pairs and they both are string.
So string now an index doesn't have a name.
We use that this keyword.
So this and here's the index or notation we use string to present the keys for our key value
pairs.
So strange.
Key and here inside this property we have a get and set method.
Now the implementation is very easy.
All we going to do is to delegate to that dictionary.
So for yet we're going to return dictionary of key.
So internally we rely on the dictionary to store the key value pairs and to be Kuki is simply a
wrapper
around that ellos implement the set method.
Again very similarly dictionary of key.
It calls value and this value is a key word which represents what is on the right side of the
assignment
operator.
Notice green on the line here.
That's resharpen highlighting feature.
So if there are areas in the code that can be improved resharper highlights them with a green
underline
.
In this case it's saying field can be made Read-Only and this is a great example of using read
only
because we don't want to accidentally re-initialize that dictionary and lose all the data be
stored
in it.
So here I can just press alternate enter and let resharpen apply the read only modify for me.
There we go.
So as we see with resharpen we tend to code less and we can delegate a lot of things to
sharper.
OK now this is ready we can go back to our program.
Let's create an instance of our HTP cooking or Kuki it calls we a little bit Googie we can
store a
key value pair using the indexer.
So Kuki of name it calls Marsch So name is the key and Marsha's the value.
And we can read that from the cooking.
So Consolo right line Kuki of name.
That's what the application.
So the cookie is working.
Now let's get back to a city cooking class.
We might be wondering why did we create an a city cookie as a wrapper around a dictionary
couldn't
we just go ahead and use that dictionary directly.
Well yes and no.
In this case in this simple example yes we could definitely just use a dictionary as an HD for
cooking
but an to be cookie is more than a dictionary for example.
It can have a property called expiry and that's the expiry date time or the cooking.
So we can go here and create an auto implemented property for that.
So Propp remember that tap that's a code snippet date time
expiry cookie can have other properties or methods and now it's more than just dictionary.
Internally it uses a dictionary for data storage.
So the takeaway from this lesson is if we're working with a class that has the semantic of a
collection
or a list or a dictionary we can improve wer code by declaring an index or and indexer is an
easier
way to access elements in that collection as opposed to having two methods like here if we
didn't have
this index or we had to create a method like public Floyd said item string key string value.
And we also had to create another method like public string get either string.
Keith there's nothing wrong with this approach but it's more efficient to just use an index or
both
in terms of the code in the class here as well as the code that we wrote in the consumer here.
OK that's it for this lecture.
I hope we enjoyed it and thank we for watching
Okay in the last section we learned about classes in this action we're going to talk about class
coupling
what is carpooling and suffering engineering.
Coupling is a measure of how interconnected classes and subsystems are at the beginning of
this course
.
I explained that a software application is composed of many classes that are package inside
various
named spaces and assemblies.
In this picture we have the classes inside an application.
I assume that we need to make a change in class A now Class B and Class F are both
dependent on Class
8 which means if a changes B and F may have to be changed or at least they need to be
recompiled and
redeploy it so that changing a may effect be an F as we see here but also Class D and Class C
are dependent
on Class B.
Similarly class she is dependent on Class F which means changing class A has a bigger
impact on our
application.
And again we see here.
Class E is dependent on Class D and class H is dependent on Class G.
So a change in class a a fixed even more of an application.
This is an example of tightly coupled design.
So an application whose classes are tightly related are dependent on each other.
It's considered to be tightly coupled application.
And this is very bad because there is a chance that we may break things along the way.
As a result of all these changes in the application in contrast to tight coupling we have a loose
coupling
so in this picture I'm demonstrating the concept of loose coupling between classes using a dot
to the
arrow.
And this is the ideal Soffer we want to minimize changes in our application.
So when we change a class we want that change to be isolated.
We don't want that change to affect other parts of the application.
Now we might ask what how do we design a Loosli couple of application.
Well there are three things we need to understand.
The first one is encapsulation which I explored in the last section.
Remember I talked about the restaurant in a restaurant.
We have various concepts like a manager and like a cashier a waiter waitress as Chef kitchen
hands a
waitress does not go to the kitchen and tell the chef how he should chop the vegetables and
how he should
cook.
That's the responsibility of the chef.
So the chef has some knowledge and some capabilities.
And if we want to model the concept of chef in software we want to encapsulate all those
concepts
in a class.
So no class from anywhere else in the application knows about details of how things are done
in that
class.
And we saw how we could use access modifiers to achieve that.
Now the next thing we need to understand is the relationship between classes which is the
topic of
the section.
And finally we need to understand interfaces interfaces are extremely important and they help
we design
Loosli couple applications.
That's why I have dedicated a separate section to interfaces so let's start with the relationships
in
general we have two types of relationships between classes.
We have inheritance and composition.
So over the next couple of lectures I'm going to talk about inheritance and composition both
in terms
of theory and practice.
And finally I'll talk about the concept of favorite composition over inheritance composition
relationships
usually result in less coupling.
And that's the meaning of this concept to favor composition over inheritance.
So let's get started.
OK inheritance in this lecture I'm going to tell we what is inheritance and why we use it then
I'm
going to show we an example of inheritance using UML notation we stands for unified
modeling language
and it's a graphical language for representing classes and their collaboration.
And finally I will show we the syntax of inheritance in C sure and then we'll do some coding.
So let's get started.
What is the inheritance.
Inheritance is simply a kind of relationship between two classes that allows one to inherit
code from
the other is usually referred to as ease a relationship.
For example we can say a car is a vehicle with inheritance we get code reuse.
That means being capture that some common code in one class and then reuse that in other
classes.
Inheritance also provides polymorphic behavior which is extremely powerful but it's beyond
the scope
of the section.
There is a separate section in this course called polymorphism and that's where we will learn
about
polymorphic behavior.
46 And let's just see how we can use inheritance to get code reuse.
Imagine we want to design an application like PowerPoint here.
I'm using keynote on Mac which is similar to PowerPoint on Windows.
So on this slide we can have objects like a shape text table and an image.
All these objects have some common attributes.
For example they have a with height and in position they also have some common behavior.
For example if I right click on this shape here we'll see Ring to front Santa's back cut copy
duplicate
and so on.
If our job is to develop an application like PowerPoint or keynote we can create classes for
each of
these objects.
For example we can have a class called Shape we can have a class called takes a class called
Table and
a class called image.
Now we don't want to duplicate all these common behavior and attributes in all these classes
so that's
where we can use inheritance to write code once and we use it in multiple contexts.
Here is the UML representation of the candy the classes for our PowerPoint application.
So I had a high level we can have a presentation object class which is where we encapsulate
those common
behavior and attributes then we can have classes like takes table an image which inherits
from presentation
object.
In this example we referred to presentation object as a parent or a base class.
Some people also refer to it as a superclass text table and image are referred to as child
derived or
subclasses in terms of syntax.
Here is how we implement inheritance in C-sharp.
So here we simply create our common class which is presentation of objects.
And then we create a new class like text that inherits from that we implement inheritance by
simply
appending a colon and the name of the base class after declaration of the trial class.
OK now let's start coding and see this concept in action.
OK let's start by creating a class called presentation object.
This class is going to be the parent or base of other classes.
So public class presentation object.
And here we can define a couple of properties like width and height
and a couple of methods like copy and duplicate.
I'm going to leave the implementation very easy so we just simply output a message on the
console So console
dot write line object.
Copy it to clipboard
object was duplicated.
Now let's put this class in a separate file.
So back here with resharpen alternate enter and enter.
Done.
Now back to our program.
Yes.
Let's create a new class that derives from presentation object.
For example text presentation object.
So this is the inheritance notation we just put a colon here and the name of the base class.
Note that in C-sharp a class can have only one parent.
Now let us define a few properties or methods that are specific to the text class.
So for example font size or font name
and maybe a method to add a hyperlink to a text or add hyperlink string here.
Now we mean to argue that we may need this feature on every presentation object and that's
perfectly
valid.
But for the sake of this example let's just add this method here because I want to demonstrate
the difference
between a parent and a child class.
So simply cancel and write line.
We added a link to.
Plus we are ok to clean up our code.
We go here and put this in a separate file.
OK let's go back to our program that C-s here.
I would like to create an object of type text so vortex it calls new text.
Now we type text dot.
OK here as we see we have members that are defined into takes class itself like the hyperlink
font
name font size but we also have members that we inherited from the parent class which is
presentation
object that includes copy method.
Duplicate method height and with properties.
We also have a few methods that we define.
In neither the presentation object nor the text class that includes the equals method.
Here are good hash code or get type or two strings.
These methods are defined in the object class which is the parent of all classes in dot net.
So when we create a class even if we don't specify the object class as its parent it
automatically
inherits the members defined in the object class or cover the object class in more details.
When we get to the section about inheritance but what I want we to take away from this
lecture is that
we added some common functionality in the presentation object class that includes a couple
of properties
like width and height and two methods like copy and duplicate and we inherited all this code
in the
takes class.
Using inheritance knownas go back to program that C-s and finish up this task.
So text dot with a 100th hundredth textiles copy.
Let's run the application.
So we got the message object copy to clipboard and the implementation of that was in the
parents class
.
Again I'll convert inheritance in more details in the section called inheritance for this section.
All I wanted to take away is that inheritance is a kind of relationship or association between
classes
and it has two benefits.
One is code reuse.
Another one is polymorphic behavior which we'll learn about soon.
I hope we enjoyed this lecture and thank we for watching
OK we got to composition in this lecture I'm going to talk about what is composition and
what are its
benefits then I'll show we how to represent composition using UML notation.
And finally I will show we how to achieve that in code.
So composition just like inheritance is another kind of relationship between two classes that
allows
one to contain the other.
We referred to composition as has a relationship.
For example we can say car has an engine just like inheritance with composition.
We get code reuse but composition is more flexible and it's a means to designing loosely
coupled applications
as we learn later in section as an example.
Imagine we're designing an application and as part of that we need to have a class called DB
migrator
that is responsible for migrating our database.
This class will be responsible for creating new tables populating them with data.
Maybe renaming columns dropping columns and stuff like that as part of that.
It requires some logging.
Perhaps we need to log each step in a text file.
Also in our application somewhere else we could have another class called installer which is
going to
be responsible for installing our application in a target environment just like DB migrator our
installer
also requires logging.
So as we see logging is something that is common between these two classes.
What we can do in this case is to create a class called logger that is responsible for logging
information
to a text file.
Here is a UML representation of this concept.
So here the Logger class has the capability to log messages in a text file.
DB migrator and installer.
They both have a relationship or association to the lower class.
The type of relationship is composition as indicated by black diamond on the left side of the
relationship
in C-sharp terms.
Composition is nothing new.
So if we want to implement what we saw in the previous diagram would simply create an
installer class
which has a private field called logger in the constructor of the installer class.
We get a logger object which we use to initialize that private field.
So for composition we don't have any special syntax like inheritance.
The related class is simply a private field in the composite class.
Now just jump into code and see the concepts in action.
OK we started by creating our Logger class which is where we have the common
functionality.
So
I'm going to keep this class as simple as possible because what we want to learn in this
section is
about relationship or association between classes.
We don't want to get distracted by details such as how to open a file to close it how to write
information
to a file.
So let's just leave that for now.
So I'm just going to create a method called log that takes a message and simply writes that to
the console
.
Now let's put this class in a separate file so alt and enter and enter back with control and
minus.
We create a new class called DB migrate for this class is going to be responsible for
migrating our
database so we create a constructor c tor tab.
There we go.
Now here we need a parameter of type logger we want to create an association to the Logger
class.
So longer longer.
I know it resharpen I can't put the cursor on this parameter here and simply press alt and enter
and
look the first item is introduce and initialize a field logger So enter it automatically created a
private
read only field as we see here and initialized it using the argument passed in the constructor.
Now let's say this class has a method like my great public void migrate and as part of
migrating which
is going to be a complex task we need to do some logging.
So all we need to do is to call the log method of the Logger class so logger that log we are
migrating
.
Blah blah blah.
Now we put this in a separate file.
We get back to program not see as using control minus.
Let's create another class call installer and we do the same technique there.
So we create a constructor ctor tab create a parameter here.
Longer longer Altan enter and enter again.
There we go.
We got the private field and get the method here.
Call it install again as part of installing the application.
Are going to log messages to our logfile.
So we simply call the logging method off the Logger class so we are installing the
application.
Now I'll just put this in a separate file to clean up our code to program dot cs.
OK now we create a DB migrator or DB migrator equals new DB migrator.
Here we need to pass a longer object.
So one way to do it is just to create another object here like new logger.
Another way is to declare a variable and assign it to the new logger and then we can pass that
variable
to the DB migratory constructor.
Let me show we this technique when creating a new installer.
So var logger it calls new logger.
Now let's create an installer var installer acost new installer.
So here again we need to pass a logger object.
So I'm just going to pass this logger object here.
Now let's call DB migrator dot migrate and installer dot install We run the application.
So here are the messages that are supposed to appear in our log.
So the interesting thing here is we declared that common functionality which was about
logging in a
separate class here and then we reused that into other classes using composition.
So as we have seen so far we have two ways to reuse code.
One is inheritance and one is composition.
They both are valid approaches but which one we use depends on the project we're working
on and its
requirements.
Generally speaking inheritance results in a more tightly coupled relationship with
composition we can
get loose coupling Plus more flexibility.
And that's the reason a lot of developers say faver composition over inheritance in the next
nature
.
I'll cover this concept in more details.
I hope we enjoyed this lecture and thank we for watching.
In the last couple of lectures we learned about inheritance and composition in this lecture I'm
going
to talk about problems with inheritance and then I'll explain that vantages of composition
over inheritance
before we start.
Let's review what we learned in the last couple of lectures.
So we saw that with inheritance we can get code reuse.
I showed we an example of a presentation object where we wrote some common code that
was inherited
by text table and image classes.
We also saw an example of code reuse using composition.
So we had a longer class where we defined the logging capability and then we use that class
in DB migrator
an installer.
Now the problem with inheritance is that it can easily be abused by amateur designers and
developers
which can easily lead to large a hierarchy of classes such hierarchies are fragile.
If we change a class on top of the hierarchy all the classes inherited from that will be
affected.
And this is because of the tight coupling that comes with inheritance.
Let me share an example.
So we can see all these problems in practice.
Imagine we are designing a game and we would like to introduce the concept of a person and
a dog Both
person and dog classes can have attributes such as age and they can have methods such as eat
and sleep
.
So we inheritance we can create an Animal class and then derive person and dog from the
animal.
Now let's see if we need to give the person and dog the capability to walk.
So we need to go in our Animal class and change that class by adding a new method called
Walk.
The problem at this stage is because boules person and dog derive from animal.
They will be affected as a result of this change.
Sometimes when we change a class the dependent class may have to be changed or at least it
has to be
recompiled and redeploy it.
OK now to make the matter worse.
Let's imagine we would like to introduce the concept of goldfish so we add a new class called
goldfish
that derives from animal.
But there is a problem here.
The problem is that the goldfish cannot walk.
So our inheritance hierarchy needs to be modified which means we have to take that walk
method outside
the Animal class and probably create another subclass called mammal where it has the
capability to walk
and then we can derive person and dog from mammal.
So as we see the hierarchy is getting changed again.
So that's the reason inheritance can easily be abused by amateur designers and developers and
it results
in large hierarchies and such hierarchies are fragile because of the tight coupling between
classes
.
Now I want to show we something I want to show we that any inheritance relationship can be
translated
to a composition and that can result in great flexibility.
So let's review the same problem and see how we can model these classes using composition.
So this time instead of person and dog deriving from animal they have an animal.
Now the first thing that may confuse we here is that a person conceptually is an animal.
At least that's how we define the concept of person in the English language.
Well that's exactly where the problem happens with inheritance.
Most amateur designers try to most offer using real world just because in the real world a
person is
an animal doesn't mean we should always use the inheritance or is a relationship between
these two classes
.
We as software engineers need to think differently.
We need to design our classes such that a change in a class is isolated and has minimal
impact on other
classes in the system and doing so requires a different way of thinking not the way that we
think in
the real world.
We basically need to think in objects.
OK back to our example.
Let's say we forgot to give the person and dog the ability to walk.
Now how can we model dogs using composition.
Well first we introduce a new class called walkable which has a method called walk these
walkable class
describes the behavior of walking for any kind of animal.
Next we create a composition between person and walkable.
Same for the dog.
Now what happens here is that a person has an animal.
And it also has a walker.
So he has the capabilities defined in both the animal and walkable.
Now Nancy we would like to add a goldfish.
So we create a new class called goldfish that is composed of animal goldfish cannot walk.
So we are not going to create an association or relationship between goldfish and walkable.
Know that in the example with inheritance I think the goldfish class broke the hierarchy.
But here we simply added the new goldfish and created the composition between goldfish
and animal person
is not modified dog is not modified animal is not modified neither is walkable.
Now let's say we would like to give our goldfish the ability to swim so we can create a new
class called
swimmable which has a method called swim and then we create a composition association
between goldfish
and swimmable.
Again none of the classes in the system have been modified.
Tomorrow we can introduce a new class called duck.
A duck is an animal.
It can walk and it can swim.
So again we can create the composition between dog animal walkable and swimmable
without any impact
on person dog and goldfish.
So as we see with composition we encapsulate some common functionality and then we
compose them together
.
We tied them together to create new classes using this technique we can create new classes
with new
capabilities of the existing classes we compose them together.
And this has minimal or zero impact on other classes.
So with composition we get great flexibility but we also get loose coupling.
How.
Let's take a look at both the composition and inheritance relationships in terms of coupling.
So here in this picture we have both an example of inheritance and composition.
In this example coupling between person and animal irrespective of the kind of relationship is
equal
.
So whether we use inheritance or composition if animal is changed person may have to be
changed or at
least needs to be recompiled and redeployed.
But there is a catch here with composition.
We get an extra benefit which is not possible with inheritance.
And that is we can replace the Animal class on the right side within the interface.
Interfaces are extremely powerful and that's the reason I I've dedicated a full section on them
for
this lecture.
Don't worry about it.
All I want we to take away from this lecture is that we have two types of relationships
between classes
.
One is inheritance which is also referred to as is a relationship.
And another one is composition which is referred to as has a relationship both inheritance and
composition
have pros and cons inheritance provides code reuse and is easier to understand then
composition in certain
examples.
For instance in the example we saw earlier we usually think a person is an animal.
So modeling that using composition like person has an animal is a little bit harder to
understand but
the bad thing about inheritance is that it creates tight coupling.
It can easily be abused and result in large hierarchies which are fragile and simple change and
propagate
to many parts of the application and that change can be very costly composition on the other
side provides
great flexibility and loose coupling but it's a little bit harder to understand.
In some cases Now I'm not telling we that inheritance is necessarily a bad thing.
In fact all inheritance and composition are great techniques but we need to use them
appropriately
.
What I wanted to take from this lecture is just because in the real world we think of a lot of
relationships
as inheritance or ease a relationship doesn't mean we need to model them the same way in
software because
again doing so can easily result in large hierarchies with many levels of inheritance.
That's it for this lecture.
I hope we enjoy it and thank we for watching
OK we got to access modifiers earlier in this course we learn about access modifiers.
We learn about public and private.
And this lecture I'm going to explain access modifiers in more detail I'm going to talk about
why access
modifiers are important and to explain that I'm going to use the blackbox metaphor.
And finally we get into C-Sharp access modifiers So let's get started.
A metaphor often used in object oriented programming is blackbox.
Look at this black box image here.
We didn't know what's inside this box.
There is limited visibility and there is just one I don't know if it's a button or a light and that's
all we can see.
We want to design our objects to look like a black box.
So there is limited visibility from the outside but it could be a lot of magic going on inside.
Now we may wonder why do we want to design our classes like a blackbox.
It all comes back to isolating changes.
The more A-class reveals about its internals or its implementation the more risky it becomes.
When we are going to change that class because there could be other parts of the system that
rely on
that implementation.
So we want to limit the visibility from the outside and make our class look like a black box.
Here's another metaphor look at this DVD player always see from the outside.
It's just a few buttons and an indicator but there's a lot of complexity inside that DVD player.
There is an electronic board with a lot of eyes sees and who knows there's a lot of complexity
there
.
What we see from the outside is called public interface.
Again we want to design our class to look like this DVD player.
So it's public interface should be very simple.
Now in C-sharp we use access modifiers to control visibility to members of a class.
We have all seen public and private.
But we also have protected internal and protected internal Let's explore these access
modifiers in detail
and memory that is declared with public is accessible from everywhere.
So in this example we have a customer class with a method that is declared as public.
With that we can create a customer object somewhere else in the code and call the promoter
method the
promote method.
It's going to be visible to the outside.
That's perfectly fine because promote should be part of public interface of the customer class.
It's all about implementation.
We may want to promote a customer and that's unexpected functionality.
Now private is the complete opposite of public.
So a member that is declared as private is only accessible from that class.
In this example in our customer object I have a method called calculate rating.
We're going to use this method as part of promoting.
So perhaps we need to do some calculation and based on the result of that.
We may promote a customer to a certain level.
This is about implementation detail.
It's about the internals of the customer class how we promote a customer.
We don't want to classes to know anything about that.
So that's an example where we can use the private modifier to limit access to this method.
So as we see an example if we create a customer object we are not going to be able to call the
calculate
rating method.
It's not going to be compliant.
OK next is protected and membered declared as protected is accessible only from the class
and it's derived
classes.
What does it mean.
Well look at our calculate rating method again here.
This time I declared it as protected instead of prime.
So this statement says accessible only from the class and its derived classes which means
outside the
class if we have a customer object we're not going to be able to call this method.
So it's a little bit similar to private.
The difference is if we derive a class from customer let's call it gold customer.
That method is going to be visible in a derived class.
Now there is a problem here.
The problem is as we explained in the last slide calculate rating is about the implementation
detail
which should be encapsulated inside the customer class itself.
We don't want it anywhere else in the code.
We know about this method because we may change it in the future.
We may rename it we may change its parameters or we may even remove it.
We don't want anywhere else in the codebase and a dependency to dismiss it.
Now the problem with the protected modifier is any classes derive from this class.
We'll still be able to see this method and that breaks encapsulation because as I have
explained throughout
this course encapsulation is about hiding the details inside the class and only revealing the
minimal
that is the public interface of a class.
So a lot of developers consider protected a bad design in the C-sharp language.
Having said that we will see a lot of places in the Dathan framework or in many other
libraries where
protected is used.
Now to make all this easier for we.
What I'm suggesting is avoided if we can and prefer to use private methods.
But if there are circumstances that we have to use protected and we have a valid reason for
that that's
OK go ahead and use it.
Just be aware that we're revealing the implementation detail of a class any of its subclasses
which
can be trouble in the future.
OK next one is internal internal is a modifier that we often use with the classes not their
members
.
It really doesn't make sense to declare a class member as internal but there are cases that we
may
declare a class as internal For example continuing from our last example imagine we have a
separate
class called Race calculator and race calculator might have a bunch of methods and some
complex logic
to calculate the rate for our customer.
Now this class is part of the implementation detail for the domain of customers.
So inside that domain it's OK for every other class to see this class.
But outside that domain we don't want anyone else to know about the existence of this class.
So how we implement that in C-sharp terms is we create a separate class library.
And in that class library we declare the race calculator class as internal.
So inside that assembly or that class library everywhere we will see this class.
But outside that assembly no one knows about this class.
Again I'm going to show we all of this stuff in the code.
So if that sounds unfamiliar don't worry about it.
And finally we've got protected internal which I would say is the most major thing in our
language.
Basically what it means is a member declared as protected internal is accessible only from the
same
assembly.
And that's because of internal or any derived classes.
And that's the result of protected.
So here's an example.
We have a customer class and it has a method called weirdo that is declared as protected
internal.
Now this is really bad both in terms of teaching learning writing code and someone reading
that code
.
It takes a lot of brainpower to understand what's going on.
I decided that in this lecture because I want my course to be comprehensive but it's very
unlikely that
we're ever going to need it.
OK.
Let's start coding and see all this access modifiers in action.
OK let's start by creating a customer class so public class customer can define a couple of
properties
like ID and name
on a method like promote.
Now let's go to the main method and create a new instance of customer Savar customer and
he calls new
customer.
Now if he type customer dot eeriest the public interface of this customer class.
So we have a few methods like equals get hash code get type 2 string which are derived from
the base
object class.
And we also have these bold members here that are defined in the Customer class itself.
So Id name properties and the promote method.
All of these together make up the public interface of the customer class.
Now back to the black box metaphor or the DVD player we want to minimize this public
interface the more
we've revealed about the class and its members the more we raise that other parts of the code
will be
dependent on those members.
So this creates more coupling which means if are going to change the implementation of our
customer
class auto parts of the code make it broken.
Let me show we how this happens.
So I'm just going to remove this.
Let's create another method.
We are going to calculate the rating of a customer.
So just public and calculate rating.
I'm going to leave out the implementation of business logic here and just return a simple
number because
we don't want to get distracted with some business rules and whatnot.
What I want to show we is in the promo method perhaps there is a call to is calculate rating
so we
can say we're rating equals calculate rating and then based on what is returned from that
method we
can make decisions.
For example if rating is whatever then console dot write line promoted to level 1 otherwise
promoted
to level 2 just keeping it simple.
Now the problem here is this method is about implementation detail of the customer class
from the outside
.
We don't really need to see this method.
What the consumers of this customer class need to see is just this couple of properties here
and to
promote Mitha how to promote method does its job which in this case means calling that
calculate rating
is no one's business.
So this is what encapsulation means.
We're just going to hide details inside and reveal the public interface.
Now the problem happens if somewhere else in the code we out of interest or curiosity of a
call to calculate
rating method
now because this is the implementation detail of the customer class tomorrow we may decide
to change
it.
For example when we decide to pass a parameter like a switch say exclude orders it might
have some meaning
in the business domain we're working on.
So we're changing this method.
And what happens is the we get this red underline here.
Now if this method is being used outside this class like in this case in our main method here
the code
is going to break.
And imagine if there were 10 other places in the code where we made a call to this method.
But in this case if this method was declared as private in the first place nowhere else we had a
call
to this method and fixing that change would be as simple as just making a change in one
place in the
code which is to promote method that is using this calculate rating method.
So here I would say exclude orders.
True but this is the reason we want to minimize the public interface of a class to the outside
world
.
Now let's get rid of this calculate rating method here.
OK.
Now let's put this customer class in a separate file to clean up our code.
So alternate enter enter.
Now back to program.
This creates a class that derives from the customer class so that we call a gold customer
and the customer here.
OK here we can have a method like offer a voucher.
So let's say we're going to give a voucher to our gold customers.
So public FOID offer voucher.
And of course this method needs some argument like a voucher object.
But again to keep things simple let's not worry about the prompter.
What I want to show we is inside this method if we use this dot.
So these are the members that we see in this class.
So he calls get hash code get type member wise clone and to a string where derived from the
base object
class.
That is the parent of every class and dot net id name and promote are derived from the
customer class
itself and offer a voucher which is indicated by bulled is declared in this class itself.
So as we see calculate rating method it's not visible here because we declared that as private.
So back to Customer class look Ganguly rating is declared as private.
And my rationale was because this is the implementation detail we want to encapsulate it.
We don't want anywhere else in the code to have dependency to this method.
Now if we changed it to protect it
and go back to our gold customer class.
Look this does.
And here we see the calculate rating method.
And here's the problem.
We created a dependency to the implementation detail of the customer class.
So again if tomorrow we're going to change that Mitha maybe we rename it maybe we add a
parameter or
maybe we even delete that method gold customer class.
It's going to be affected.
Let me show we this in action.
So imagine as part of offering voucher we're going to call this method and let's pass whatever
switch
here and get a rating here.
And based on that rating we're going to do some logic.
Now if tomorrow we go to the customer class
and decide to totally drop this method maybe our business logic or promoting a customer is
changed.
So I'm just going to remove this method and let's say I'm going to change the logic of
promote method
that promote logic change.
Now see what happens in the gold customer class.
So the calculate rating method does not exist anymore because we deleted it from the parent.
Again here is where encapsulation is broken.
So try to avoid protected unless we have a valid reason to use it.
For example if we know that the concept of calculate rating is completely stable in the
business too
many have been working on it it's OK to use that.
Also as I said there are some design patterns that use protected methods as part of their
implementation
.
OK let's move on and see the internal modifier.
So I'm going to just remove this class
ok to see the internal in action we need to move our customer class to a separate assembly.
So what I'm going to do is right click on the solution go to I'd actually we're never going to
see
that in the screencast.
So I just drag and drop the solution explorer to the left so we can see right click on the
solution
.
I had new project and we select class library.
So with a class library we create DL L are dynamically linked library and we can reference
that in various
applications.
So give it a name.
Let's say we're building an application for Amazon.
So.
So I'm going to call this class library Amazon
no by default we have class 1 in this project this class library I'm going to remove that
and then I move this customer in class inside the Amazon class library.
Yes.
When we open it know that here we have the old namespace.
So we need to change that because now the customer class is inside the Amazon project.
So with resharpened this is pretty easy.
We just put the cursor here and Polton enter the first item says move declarations to
namespace Amazon
enter down.
So here in this project we're going to implement our business logic.
We have the customer class and we also are going to create a new class for calculating rating
of the
customer.
So a public class rate calculator and it could have a bunch of methods and properties and
fields.
I'm just going to keep it simple.
So let's have a method called calculate which gets the customer object.
And for simplicity let's just return zero in the promote method of our customer.
I'm going to make a call to this calculator.
So our calculator goes new calculator.
We rate calculator and rating equals calculator dobbed calculate and I pass this as the object
as the
customer object to that method.
And based on that rating we can do some conditional statements and decide how to promote
the customer
.
I need to add a caveat here.
Generally speaking it's not a good practice to instantiate a new object like the race calculator
inside
the method here because this creates coupling or dependency to this object.
When we get to the section about interfaces we show we a better way to implement this code
or no let's
just move on.
So let's recap.
First of all I'm going to put this class in a separate file.
So alternate enter and enter again.
All right let's recap.
We have Amazon class library which is going to be our DSL.
We two classes customer and race calculator.
Rachel peculier simply has a calculator method and returns 0 in the Customer class as part of
promoting
.
We use the calculator object to calculate the rating.
Now let's clean this up.
Back to our program here we have the customer object right.
I just notice a problem here that when we copy it when we drag and dropped the customer
object from
X is my first project inside Amazon.
It was not deleted from the source.
I think I made a mistake while recording.
So I'm just going to delete this class.
All right.
Now in our program which is in the access money far as the customer is not detected.
So we put the cursor here and resharpen has this red icon here if we press alt and into it we
can activate
that.
So I was suggesting to reference Amazon what it does is it goes to the references folder and
as a reference
to Amazon.
If we don't have any sharper what we need to do is still at that and delete the using statement
on the top
.
So see the customer class is not detects it.
We simply right click on references either reference then expand solution.
So in our solution we have another project called Amazon I select that and click OK.
So now we have a reference to that assembly that class library and we can use any obvious
classes.
I know to use the customer.
We simply go on the top type using Amazon because that's the name space.
So we see with resharpen it's much easier.
We don't have to do all these manual steps.
All right let's move on now.
Let me show we that in the main message here.
If we type Amazon which is the name space dot we see two classes customer and race
calculator.
In this case race calculator is used as part of promoting a customer so we can argue that it's
the internals
of the customer or the Amazon domain.
And based on the capture lation principle of object oriented programming we shouldn't reveal
the implementation
anywhere in the code.
So the problem is if we use this rate calculator here calculator.
Now these projects are access modifiers.
Is program class in the main method.
We have a dependency to this calculator object.
In the future if we go to our Amazon class library and decide to get rid of this red calculator
let's
remove this class here.
The areas that are affected.
One is inside the customer class here.
But we also have this line in so many holes in the code that is broken.
And that is not good because this way we could have 10 other places in the code where there
is a dependency
the rate calculator which is about implementation.
If it declared this rate calculator as internal It would have been visible inside this class library
here but not anywhere else in the code.
So let me add that rate calculator back here.
So I have a new class rate calculator
and put that calculator method back calculate return zero.
Now this summer declared as internal.
What happens is in the Customer class this class is visible because he's part of the same
assembly but
the outer disassembly when we go to access modifiers we cannot access this class.
The red underline it says can love access internal class rate calculator here.
Well that's pretty much for this lecture.
I hope we enjoy it.
And thank we for watching
OK earlier in this course in the section about classes we learn about constructor's in this
lecture
we're going to learn more about constructors and inheritance.
There are two things we need to know about constructors when it comes to inheritance.
First is that during the instantiation of an object the base class constructors are always
executed
first and the second is base class constructors are not inherited.
So in a derived class we need to redefine wer constructors.
It's easier to explain these with an example.
So here we have a vehicle class with a private field called registration number the vehicle
class has
a constructor that takes a parameter of type string called registration number and we use this
argument
to initialize the private field here.
Now let's say we would like to create a class that derives from be called.
So our class can look like this.
The core class that derives from Mieko know that I have redefined a constructor with a string
parameter
for the registration number here.
The reason for that is even though we define a constructor in the vehicle class.
It's not going to be inherited by the car class.
So we need to redefine the constructor here.
But what are we going to write in this constructor.
Well I've highlighted this line with red which means this is not valid.
In fact if we read this code it's not going to be compiled.
We're going to get an error.
Why.
Because in the vehicle class we declared registration number as private.
Let's take a look at the vehicle class again.
So note that the registration number is declared as private which means it's not going to be
accessible
in the current class and in the lecture about access modifiers.
I explained why private is a better choice than Protector's.
So back to our car class at this point we are not going to be able to access the registration
number
field because it's the implementation detail of the base class which is vehicle which we would
like
to encapsulate in the vehicle class itself.
So that detail is not leaked anywhere else in our program.
No instead if it declared that as protected just let's say for argument's sake we would be able
to access
that field here.
But still it's not a good idea to initialize that field here because we define this concept
somewhere
else in the code in the vehicle class's constructor.
So we should not repeat ourself.
Instead what we need to do here is to reuse that code we wrote in the vehicle classes
constructor how
we do that is using the base keyword.
So all we need to do here is when declaring the constructor for the car class before opening
the body
of the method here we up and colon base and here base is simply a way to access the base
class.
The syntax simply represents a method call.
Imagine we're calling a method called base.
And here we're passing an argument to that method.
That method is simply the constructor of the vehicle class.
So the constructor of the car class receives an argument called registration number.
And here we simply pass it to the base classes constructor and in the constructor of the car
class here
we should write anything specific to the initialization of the car class itself.
OK.
Now let's start coding and see this concept in action.
OK I'm going to show we a few different things here.
First let's start by creating a vehicle class so public class recall list creates a default or
parameterless
constructor.
So a seat or tab.
And here we use console that writes line to log a message to the console.
So CW type vehicle is being initialized.
Now those define a car class that derives from the call.
And again here define a constructor that simply logs a message to the console.
So ctor tab console dot write line car is being an issue.
Licet OK.
Now to clean up our code we put these classes in separate files.
So we go here Polton enter enter control minus back here
again one more time back to program.
Now here we create a core object Savar car equals new car.
There we go.
Let's run this application.
Note that we got two messages on the console.
First Monday's vehicle is being initialized and the second one is car is being initialized.
So what we see here is when we create an object the constructor of the base class is always
executed
first.
OK now let's extend this example and take a look at the base keyword.
B go back to our vehicle class.
So I'm going to leave this default constructor here but I'm also going to create another
constructor
that takes a parameter called registration number.
So ctor tab.
This one is going to take we parameters so String registration number.
And here we can use Altan enter.
And the first item is introduced and initialize field registration number.
And as we see what happens is resharpen automatically creates a private Read-Only string
field called
registration number if we like this kind of fast coding techniques.
I have a course called Double wer coding speed where I teach we lots of techniques to write
code faster
and easier.
So Mac for example here the vehicle class has two constructors one is default or
parameterless and the
other one takes a parameter of type string.
Now let's go to our car class.
At this point everything is fine.
The reason for that is the vehicle class has a default or parameterless constructor.
So we can create an object of type car.
And at this point first the default or parameterless constructor of the vehicle is executed.
And then this constructor here will be executed.
But let's see what happens if we go to the Ricoh class and comments out this default
constructor.
Now back to our car class.
Look we got a red underline here and the error is saying based glass Veikko doesn't contain a
parameterless
constructor.
What does this mean.
Basically what's happening here is when we create an object of type car the runtime first tries
to create
an object of type vehicle but because the vehicle type does not have a default or prominences
constructor
the runtime doesn't know how to create an object of type recall.
So what we need to do here is back to the core class we use the base keyword to call one of
the constructors
of the vehicle class and how we do it is very simple.
Enter Colon.
We use the base keyword open brackets.
And here we go.
We have one constructor that takes a string prompter called registration number.
Now at this point we need to supply some value.
We can simply hard code something here but it's not a good idea because we don't want to
hard code and
registration number here.
A better way is to receive a parameter called registration number in the car class's
constructor.
So here string registration number and whatever we receive here we simply pass it to the base
class
.
There we go.
Now just modify the message belong on the console to see the order of execution in more
detail.
So what I'm going to do is I simply add the registration number here
registration number and we do a similar technique in the vehicle class's constructor
.
Vehicle is being initialized.
And here the prompter is going to be registration number.
Let's run the application again.
We had a builder and see what's happening here double click here.
Here the aerosolize car does not contain a constructor that takes 0 arguments.
So what's happening here is we change the constructor of the car class to receive an
argument.
But here we forgot to supply one.
So let's just add the registration number.
X why is that 1 2 3 4.
On that occasion again not that the vehicle is being initialized first and then the car is being
initialized
.
And in both constructors receive a parameter and that is what we passed here during
instantiation of
the car object.
Well that's pretty much it for this lecture.
I hope we enjoyed it and thank we for watching
Okay at this point we know how to use inheritance in C-sharp when we have a base and a
derived class
.
There are situations where we need to convert an object to a base or a derived class reference.
And that's what they're going to learn in this lecture.
So I'm going to talk about conversion from a derived class to a base class which is referred to
as upcast
think.
And then I'm going to talk about the opposites.
So from a base class to a derived class which is referred to as downcasting.
And finally I will explain that as in is key words.
So let's assume we have a class called shape on a classical circle that derives from the shape
to keep
things simple.
I have excluded the members of these classes in this example.
OK now let's talk about casting.
In this example we have an object called Circle which is of type circle as we see from this
example
in C-sharp we can convert an object like circle to its base class reference.
In this case shape no conversion is required.
So it's implicit.
And now let's look at downcasting.
So falling from our last example we can convert shape to a circle object using an explicit cast
as we
see in the example.
Now one thing we need to be cautious about is that casting can throw an invalid cast an
exception in
this example our shape object is actually pointing to a circle object and runtime.
So we can cast it to a circle but if we try to cast it to another type like a car it's going to throw
an exception.
So here is an example.
We cannot cast a shape to a car and that throws an invalid cast exception.
Now to prevent this from happening we can use the as keyword.
So imagine we have an object and we would like to convert it to a car with explicit cast as we
see
here.
We may get an exception a safer way is to use the as keyword so when we use the as
keyword.
If the object cannot be converted to the target type we are not going to get an exception.
Instead what is return will be no.
So in the next line we can check if the result is not known.
And then we can do whatever we want with that object.
We also have is key word with the key word we can check the type of an object.
So we can't say if an object is a car then we can safely cast it to the car.
Otherwise we want to any casting.
OK let's jump into cold and see all these concepts in action plus some real world examples of
where
we need to do conversion between objects.
OK.
We're going to see a few interesting and useful things in this with we.
Let's start by creating a class called Shape.
So the public class shape the intention here is to model an application like PowerPoint or
keynote on
Mac.
So we have the concept of shape which is going to be common across other concepts such as
text table
image whatever.
So each shape in our PowerPoint application is going to have at least width and height.
So we create two properties width and height and at least it needs a position so we can have
an x and
y.
We also need a method to draw a shape so public voyde draw to keep things simple.
I'm just going to leave out the implementation for now.
So let's move our shape glass to a different file just like we have done in other exercises.
Altan enter enter back with control and minus.
Now let's create a class called text that derives from shape.
Now are tigs class needs some additional properties like font name or font size so font size
and font
name
again we're going to move this class to a separate file.
So
back to our program.
Now let's create an object of type text
text text it calls new text
not want to show we of casting so we can declare a viable of type shape and simply assign it
to text
as we see.
No conversion is required.
So we can implicitly convert an object reference like text based class reference like shape.
And this is very powerful.
I'm going to show we how are going to use that in real world applications.
But before we get there let me tell we a little bit more about what is happening behind the
scene.
Both this text and shape objects are actually pointing to the same object in memory.
Well it's more accurate to say takes and shape are both references to the same object in
memory but
they have different views what it means is if I go here and say text dot I can see all the
properties
of a Takes object.
So font name font size plus the ones inherited from the base class.
But if we use the shape reference we see a more limited view.
So as we see font name and font size are not there even though at runtime the object that we
have in
memory does have those properties.
But we are not going to see them if we use the shape reference.
Now we might wonder why do we need a more limited view of an object.
We'll get there.
I'll explain that in a real war scenario.
But for now let's just do a simple experiment.
So what I'm going to do is first I use that takes object and set with two 200.
Now I use the shape reference and modified that with two hundred.
Finally I'm going to display the width of the text on the console console dot write line takes
that
with what value do we think we are going to get on the console hundred.
Because all text and shape are references to the same object.
They just have different views.
Let's run the application and verify this.
There we go.
So we got 100.
Now what's the point of converting an object reference to its base class reference.
Well this is actually very powerful.
And that brings us to a new topic called polymorphism which we're going to see in the next
section.
But for this video let me give we some insight about where we're going to use this kind of
conversion
in a real war scenario.
Well first of all let me clean up all this code here.
OK.
In Dathan framework we have a class called stream reader which we use to read data from
any stream of
any kind.
So let's create an object of type A stream reader so stream reader reader icles News Stream
reader.
OK.
That Here we have a few overloads or the constructor of this class.
The simplest one is the one that takes a stream object.
In the framework stream is the base or parent of every kind of a stream.
For example file a stream or memory Stream.
Let's take a look at them in the Object Browser.
So we go to View and then Object Browser
in the search box for this type file stream.
So here is our file stream class which is defined in system data.
Io namespace.
Here's the declaration of the file stream class.
Note that it derives from a stream.
And here are the members of the final string.
So we use a file a stream object to work with the file.
It has methods to read from a file or write to a file.
Now let's take a look at the memory stream.
So like here.
Search for memory stream
again here in the declaration of memory stream.
Note that it derives from Stream.
Now let's get back to our program
in practical terms.
In the constructor of a stream reader we can pass any object whose type we arrives from the
stream
class without any conversion.
So what we can do here is we can simply pass a new file the stream or we can pass a memory
stream.
So any class that derives from the stream class.
So back to our upcast in concept the object we're sent here will automatically be upcast to its
parent
class which is string.
Let's take a look at another example.
So I'm going to come at this out
we have a class called array list which we can use to stir objects in a list array list lists a cause
or a list or we could use var here to keep our code cleaner.
Now let's take a look at the Add method.
The method takes on an argument of type objects and remember objects is the parent of all
classes in
the docking framework.
So essentially what we can do here is we can't pass any object to this method and no
conversion is required
.
So I can either number here or I can add a string or I can add a text object and all of these
objects
will be implicitly converted to the base object class.
Now in real world applications we should not really use the Israeli's class because it's not a
typesafe
kind of list.
As we see we can store a different kind of object in every element.
So in this example the first element is a number.
The second one is in the string and the third one is a Takes object.
So at runtime we make exceptions as a result of converting array elements to target types.
A better way is to use generic lists so we can use a generic list class like.
Or let's call it another list it calls new list.
This is a generic class a generic class takes a parameter which is used to enforce some kind of
concentrates
on that class.
So for example if I put integer here my list is going to be a list of integers.
So every element in the list is going to be an integer.
Or we could use a list of shapes which means every element is going to be of type shape so
we can store
a shape object or an instance of any of we ref classes.
OK so that's all about upcast Singh.
Now let's take a look at downcasting.
So let's clean up all the code here.
I'm going to declare a shape object.
So shape shape.
I know I can assign it to a text.
So even though at compile time the type of our shape object here is shape at runtime its type
will be
text.
Let me show we what I mean by that.
So I put a breakpoint here using f 9.
I run the application in the debug mode using F5.
Now we press F 10.
OK here in the watch window.
Let's clean up whatever we had here.
So I just type shape.
So this is a way to watch objects and their content in C-sharp.
So as we see our shape object is actually a type text me when do I declare it as shape.
Now the problem with this shape object is if we type shape dot we get a limited view.
As I explained earlier.
So we're not going to be able to access the properties defined in the takes object.
So that's where we need to downcast the shape object.
So what I would do is I declare a text quoted text and I apply a cast here.
So I want to convert a shape to a text.
Now with this object we have access to every property in the takes class like fonts name or
font size
.
Now we might wonder what is a real world example of having to downcast optics.
Well to demonstrate that I'm going to close this project
and create a new project
I'm going to use WPA application.
Or we could use Windows form application.
Either of these are used to build desktop applications for Windows.
So let's go ahead with WPA application.
Leave the defaults in terms of name or location.
It doesn't really matter.
OK.
OK.
Here's our designer and as we see we have a blank form.
So if we run this application which is going to see a blank form.
There we go.
So just a blank form.
Let me close that.
Now what I want to do is to put a button on this form.
So from the toolbox find under common WPX controls.
Drag and drop button here.
Now double click that the designer creates a method here called a button underlined click.
This method will be executed when the user clicks on the button.
We can't just display a message here.
Message Box start to show Hello world.
Let's run the application.
So I click the button and we got this hello word message.
Right.
OK now let's take a look at the parameters of this method.
The first one is of type Object and he's the center or source of that click event.
In this case that's going to be a button.
But the problem is if I type sender dot I don't see any properties or methods related to the
button
class.
All I see are the members defined in the object class.
This is a very common case where we need to downcast and object.
So we can do a cast of button and store that in a separate variable like button.
And here we have access to all these properties and methods of the Button class there we go.
Now note that in this example because I was sure that this method is the click handler for a
button
it's safe to cast it to a button like this.
But if there are situations where wer downcasting an object and we're not sure about the
runtime type
of an object that's where we use the as keyword.
So alternatively we could do sender as button and then if Button is not know it we could have
any code
that requires to access a button object.
So at this point I know the conversion was successful and I can type BOTTEN dot actual
height.
Let's put we on the in a message box.
I would need to convert that to a string because actual height is a number and the show
method of the
message box requires a string.
So let's run this application and I click the button that we got.
Twenty one point ninety six.
OK I know we got the second message box which is the hello world.
OK.
Well that's pretty much it for this lecture.
What they want we to take away is in C-sharp of casting is place it.
So we can simply convert an object reference to its base class reference.
In practical terms that means wherever a method requires an object of a given type we can
pass an object
of that type or any types that derives from that type.
The second thing I want we to take away from this lecture is in situations like handling the
click
of a button or anywhere where in wer method will we get an argument and then the argument
gives we
a limited view to that object.
We can use downcasting to convert that object to a more specific type and to do that we can
use an
explicit cast or the ASCII word.
I hope we enjoyed this lecture and thank we for watching.
OK we go to boxing and unboxing and this video I'm going to talk about the concept of value
types and
reference types.
And from there relate to boxing and unboxing so all types and C-Sharp are divided into two
categories
value types and reference types
value types are stored on the stack.
What is this stack when wer program is executed a limited amount of space and the memory
is allocated
to each thread of wer program and this space is used to store simple values like all primitive
types
like Byte integer float char pool as well as the struct type values stored in the stack.
Have a short lifetime which means as soon as they go out of scope they immediately get
kicked off the
stack by the runtime.
We also have reference types reference types are stored in the heap which is a larger amount
of memory
.
We use Hieb to store objects that require a longer lifetime examples of reference types and C-
Sharp
are basically any classes.
So the object class that is the parent of all classes or the Array class or the String class or let's
say we have a custom class called DB migrated.
These are all examples of reference types.
Now why does it matter.
Well earlier in the section we learned that an object reference can be implicitly converted to a
base
class for reference.
And here's the example I showed we.
So here we create an instance of a Sirico class and then we can't simply assign it to a shape
reference
.
So this object reference can be implicitly converted to a base class reference.
No conversion is required.
We also learn that the object class is the base of all classes in the Dathan framework.
So taking the last example we can modify to something like this.
So since the object class is the base of all classes in the framework we can't simply pointed to
any
objects and that object reference will be implicitly converted to the object reference.
Now that brings us an interesting scenario where we put a value type.
On the right side of the assignment operator and this is what we call boxing.
So in a formal definition boxing is the process of converting a value type instance to an
object reference
.
So as an example here I have a number that is of type integer and since object is the base of
all classes
in the dominant framework we can declare an object variable and I assign it a value type as
we see
here.
Or a different way to write the same code.
It's like this.
We simply declare an object variable and I assign it the value.
What happens behind the scene is its value gets boxed by the CLR and stored in the heap
instead of the
stack.
So let's take a look at the memory visualization.
So assuming that here we have a stack and a heap and on the stack we have a variable called
number with
the value of 10.
Now when boxing happens C-L are creates an object in the heap and then creates a reference
in the stack
that points to that object.
So as we see the value is now stored in the heap along with an object reference in the stack
when boxing
is the opposite of boxing.
So in this example we have an object that is assigned 10.
So at this point boxing happens.
Now when we cast an object to an integer unboxing happens and the result is we get a new
variable on
the stack called number with a value of 10.
All we need to know about boxing and unboxing is that they both have a performance penalty
because
of that extra object creation.
And that's something we should avoid if possible it's best to show this with an example.
So let's start coding and see boxing and unboxing in action.
OK.
Earlier I told we about the elite class.
This create an object of type or at least
none that take a look at the method
as we see it the method takes an argument of type objects which means because the object
class is the
parent of all classes.
We can pass any objects here so I can pass a number here or a string or a date time
or anything.
Now there are two problems with the array list.
The first one is type safety as we see.
Each element here has a different type.
So we lose type safety which means at runtime if I try to get the second element of this list
and cast
into an integer we are going to get an exception.
So let's declare a variable called number and get the second argument of this list and cast it to
an
integer.
Now the second argument is of type string.
So if we do casting here we're going to get an invalid cast exception.
So that's one problem with the array list but there is another problem.
The problem is the add method takes an argument of type Object which means if we set a
value type here
boxing will happen and subsequently when we get that value back and cast it on boxing
happens.
So in this example one is an integer.
It's a value type.
And here we get boxing.
String is a reference.
And in this case boxing is not going to happen.
And daytime is a structure as we see here.
The structure is also evaluated.
So here boxing happens.
Another way is to use a generic list.
So instead let's create another list and use the generic list here and let's say we want to store a
list of numbers so we pass integer as a generic parameter is generic list class is defined in
system
that collection is the generic namespace.
And now let's take a look at the method.
So another list at look it receives an argument of type integer as opposed to object.
So we get type safety which means every element is going to be an integer and no boxing will
happen
because internally this list stores a list of integers not a list of objects.
Let me show we another example.
So this time I create a list of names and I use a generic list of strength.
Now if we access the adman's that every element is a string.
Again we have type safety and no boxing.
So the lesson here is when we're working with a class if we're calling a method and that
method gets
an argument of type Object be aware that if we pass a value type there boxing is going to
happen.
And this has a performance penalty.
It's better to use a generic implementation of that class if it exists.
Well that's pretty much all we need to know about boxing and unboxing.
I hope we enjoy this lecture.
And thank we for watching
OK we go to method over writing and this lecture I'm going to talk about what is method
overriding and
introduce we to two powerful keywords in C-sharp called Virtual and overwrite method or
rightthing
is simply modifying the implementation of an inherited method.
What does it mean when we use inheritance.
There are times that we may want to modify the implementation of a method that we
inherited from a base
class.
Maybe that implementation doesn't apply to a derived class.
That's where we can use method overwriting.
So we override the implementation of an inherited method.
Sometimes developers need to get confused between method overriding vs method
overloading.
Overloading is having a method with the same name but different signatures overwriting on
the other
side is about changing the implementation of an inherited method.
Let's take a look at an example.
So throughout this course we learn about the Shape class so it's the base class where are
imaginary
PowerPoint application.
The Shape class can have properties like with height position and so on and it can also have
some methods
to keep things simple.
I've only added the draw method here now where we do have a class like circle or image
from the shape
.
The algorithm we use for drawing a circle or an image is different so that's where we need to
change
that implementation of the drama that we inherited from the parent Shape class.
Doing this in C Sharp is very simple and that's where we use the virtual and override
keywords so we
can change wer example to something like this.
So all we do here is we decorate the dramas in the base class with a virtual keyword and that
gives
us the ability to change that implementation in a derived class and to do that we use the
override keyword
in the derived class.
No that we don't necessarily have to overwrite or change that implementation.
But if we want we can do so by applying the overwrite to that drama or in the derived class.
If we don't override that method the default implementation defined in the base class will be
inherited
.
Now this technique is extremely powerful and that's one way to implement polymorphic
behavior in C-sharp
.
Now I want to keep theory in this lecture to a minimum and focus on practicality.
So let's start coding and see polymorphism and method overriding in action.
OK the example is going to show we in this lecture.
I believe it's an eye opener.
So let's take a look at this piece of code I have written which is an example of a poorly
written piece
of code.
I'll show we how to change this code and make it much better.
So let's take a look at the classes we have in this project.
We have a class called Shape which has a few properties like width length and position which
is simply
an X and Y and an enumeration called Shape type which determines the type of that shape.
Let's take a look at the shape type enumeration.
So shape type in an enumeration.
And currently we have support for circles and rectangles.
We also have a class called Canvas.
Here's our canvas class so this class simply has a method called draw shapes which receives a
list of
shapes.
Inside this method we iterate over the list of shapes and then we do a switch on the type of
the shape
.
So if the shape type is circle here we have an algorithm that draws a circle or if the shape is
rectangle
.
Here we are going to have the algorithm for drawing a rectangle.
Now this code has a problem and even though it's a classic example that I'm using for
teaching.
I've seen the exact same pattern in many real world applications so let's see what's the
problem with
this code.
The problem is that next time we decide to add support for a different type of shape let's say a
triangle
.
We have to go here to shape type enumeration.
Add a new member here triangle and then we have to go modify the can with class.
Here we are going to have another case statement like.
Case shape type that triangle.
And of course here we're going to have some algorithm for drawing a triangle.
The problem is every time we define a new shape type.
This method is going to be changed and as a result the class that contains this method has to
be recompiled
and redeploys which means any class in the application that is dependent on this class also
needs to
be recompiled and redeployed.
Same for the shape type every time we modify this enumeration and add a new member any
classes that
is referencing this again is going to be recompiled.
So there is a lot of tight coupling here and there is also an other problem.
Take a look at the canvas class.
Imagine if we're going to have support for 10 different types of shapes.
This method is going to get really really fat.
Well we may argue that we can refactor some of this logic here into separate methods but still
the
parent method here draw shapes is going to be fat and complex.
Now the reason we have this problem with this code is because the shape class itself has only
properties
it doesn't have any behavior it doesn't have any methods like the encapsulation principle of
object
oriented programming.
We want to encapsulate data and behavior or methods in the same unit.
That's a class application design or develop this way like the one we see here have data
somewhere
whereas behavior is somewhere else.
In this example data is here but behavior is inside is Kamis matter.
So we need to encapsulate them into one unit.
So let's see what's a better way to write an application like this.
So the first thing is I'm going to create a new class called circle.
Currently we don't have inheritance here.
We just have a shape class that has a type.
So let's create a circle
and be derived from shape
and another class Rectangle is also a shape.
Now I'm going to get rid of this enumeration here because I want the concept of type of shape
be determined
in a derived class so a circle is a type of shape rectangle is a type of shape.
We don't need the shape type enumeration anymore so let's remove this.
And obviously I remove it from the solution here as well.
Now back to our canvas class.
Obviously this code is broken because the enumeration doesn't exist anymore and that doesn't
matter
at all because as we explained here is the behavior around the concept of a circle.
So we need to encapsulate that behavior and the data related to that behavior in one unit.
So we go back to our circle class here first bonito either method here called draw.
So the drama that defines the concept of drawing a shape.
Now this method will be inherited by these derived classes but how we draw a circle is
different from
a rectangle.
The algorithm is different.
And that's where we use method overwriting.
So we declare this method as virtual.
So we get a chance to change its implementation in a derived class.
So here I go to the Circle class we simply type override.
And note that visual studio automatically lists all the methods that we can overwrite.
So here is the draw method.
And here are three methods that we have inherited from the base object class.
Equals get hash code and to string.
I will show we an example of overwriting one of these methods later.
So let's just get back to our draw method here.
Now by default visual studio automatically as this base draw method call here what does it
mean.
Base is a reference to the parent class.
So here we can write any code specific to the Circo class itself.
And then before or after if we need to we can pass the execution to the dramas that define in
the parent
class.
In this example we don't really need this because the drama that we have in the parent shape
class has
no implementation.
It's just an empty method.
So remove this and here I'll have the algorithm for drawing a circle.
Let's get back to our canvas class.
Now that here is the algorithm for drawing a circle which was not encapsulated with the data
about a
circle in one unit.
The behavior was different somewhere else in the application.
And that's a symptom of poorly designed application.
So I just cut this from here and put it back here.
We do a similar technique with the rectangle class.
So override tab and enter.
We don't need this line.
Now let's get back to the campus and grab this line which is we're drawing a rectangle
and paste it here.
Now let's go back to the camis again.
So we don't need the circle and rectangle anymore.
Elysée crafting our application does not have support for triangle.
Then I'll show we how we can add support for triangled without breaking existing code
without the need
to recompile and redeploy many classes.
So let's get rid of all this switch block here.
Now inside the foreach block what we do is we simply call the draw method of the shape and
here's where
the magic happens.
Let's take a look here.
So the parameter or this method is of type list of shapes so every element of this list is going
to
be a shape object or an object whose type derives from the shape class.
And that's what we learn earlier.
So at runtime what happens here is we iterate over this list of shapes what we may have a
circle in
the first element of this list or the second element might be a rectangle.
So when we call this draw method here even though we are talking about shapes at runtime
that shape
object might be a circle or a rectangle.
So when we call the drama it the draw in the circle will be called all the drawing the rectangle
will
be called and this is what we call polymorphism.
So pulling in Greek means many more means of form.
Polymorphism means many forms.
So we see we have the concept of shape and the concept of drawing a shape.
But that concept can have different forms depending on the objects we have and run time.
Let's get back to the campus class again.
Look at the implementation here is very simple.
OK now let's go to the program class.
Here in the main method first we create a list of shapes.
Then we create a canvas and we passed a list of shapes that draw shapes method on the
canvas.
Previously I used that type enumeration and that's why.
Because I deleted the type enumeration.
This code is now broken.
Basically what we need to do here is to store different types of shapes in this list.
So I want the first object to be a circle so
assign a new circle here.
And let's not worry about setting the properties.
And here let's put the rectangle
now to show we exactly what happens of runtime.
I put a breakpoint here real f 9.
Run the application into debug mode with f 5.
Now we can't step into this method with F 11.
OK now let's put a watch on the shapes object passed to this method.
So in the watch window type shapes.
So that's a list with two objects.
Let's expand this list.
Note that the first object is a circle and the second one is a rectangle again because it's a list
of
shapes an element in the list can be a shape object or an object was typed derives from the
shape Achillas
collapses.
Now we continue execution with 10.
One more one more one more one more.
Now we are inside the for each block.
Let us put a watch on the shape object.
So here is the current shape and as we see it's a circle.
Let's continue exaction with F 10.
No we step into this method with F 11.
Note that now we are inside the drama of a circle.
So let's continue execution with 10 or more one more one more.
Now this I torsion is over.
Let's continue execution.
Here is the second alteration.
And note that in the watch window now our shape object is referencing a rectangle.
So if we continue execution here.
Now we step into this drama.
It takes us to the drama of the rectangle.
Analysis of the debugger which shift an EF 5.
So back to our campus class again I want to emphasize this one more time.
So even though here we are dealing with a list of shapes and runtime the objects we have in
the list
can be a shape or any object was type derived from the shape.
Now because we declared the dramas are in the shape class as virtual That gives us the ability
to override
it in derived classes which means at runtime.
If this shape is a circle the draw method of the circle will be called.
Or if it's a rectangle the draw method of the rectangle will be called.
Now what's the benefit of this approach.
There are a number of benefits.
The first one is if we remember.
Previously we had various algorithms in this dropships method.
We had the algorithm for drawing a rectangle we had an algorithm for drawing a circle and
imagine as
we add support for more shapes.
This method is going to get fatter and fatter.
We fix this problem by using encapsulation such that we encapsulate the concept of drawing
a circle
as well as the attributes or properties about a circle in one unit.
So here if we want to have some extra properties about the circle we can define them here.
All these members in the circle class I highly related so pieces of the code that are related are
in
one unit as opposed to all over the place.
So this way the circle class doesn't get bulky because it only knows about the concept of
circle.
Similarly the canvas class doesn't get bulky either.
The implementation is very simple.
Now tomorrow if I decide to add support for a different type of shape let's say a triangle.
This method is not going to change.
Let's see what happens.
So we go back here to our shape file and this create a new class
called Triangle and derived from shape.
And now overwrite the drama.
And here we implement the algorithm for drawing a triangle so cancel that right line draw
correct.
Sorry triangle.
Now the interesting thing here is we simply added a new class called Triangle.
But this had absolutely no impact on the shape class because shape class knows nothing
about Triangle
.
It also had absolutely no effect on the rectangle rectangle is not changed it's not a factor.
Same for circle and same for Calvus are our campus class only knows about the shapes
whatever shape
they are at runtime.
Who knows who cares.
The canvas doesn't have to worry about it.
So this way with polymorphism we can create new shapes by simply creating new classes.
And that has absolutely zero impact in our existing classes.
And this is a sign of loosely coupled applications.
Well that's pretty much it for this lecture.
I hope we enjoyed it and thank we for watching.
In the last lecture we saw how we used interfaces to improve the testability of our
application.
In this lecture we're going to see how interfaces health with extensibility are application.
So similar to The Last Lecture.
We're not going to have any slides here.
So let's jump into Visual Studio and start coding.
OK let's if we like to create a tool for migrating a database we can start by creating a class
called
DB migrator
class can have a singular method called migrate which can be void.
And here we are going to have details of migrating the database now to keep things simple.
I'm not going to implement that here but what I want to show we is how we can create
extensibility
points here by using interfaces.
For now let's just assume that we would like to log some messages on the console as the
database is
being migrated for example we may want to display the time the migration started.
We may display the time migration finished if there were any problems along the way.
We can display them on the console.
So one way to implement something like that is to go here and say all right line
migration started at
and here we can have the current date time
potentially we can have another console in dot write line here to indicate where in-migration
finished
.
Now the problem with this kind of implementation is if tomorrow we decide to use a file or a
database
instead of the console we have to come back to this method and change it.
Which means this class has to be recompiled and redeployed.
Let me tell we something interesting here.
In an ideal world we would like to design or suffer such that we can change its behavior
without changing
its code.
We might wonder how is that possible.
Well it is possible by using extensibility which means instead of changing the code in the
existing
classes simply add in new classes that change the behavior of the system.
With this way of thinking every time we want to change the behavior of our solver we create
new classes
.
And as we learn from the last lecture we can write unit tests or any kind of automated test
only for
those new classes.
The impact should be minimal to zero on the existing classes because we are not changing the
existing
code.
Now as much as this idea sounds beautiful sometimes it's a little bit costly to implement.
So in practical terms we can not design software such that every change can be implemented
using an
extensibility mechanism.
Well it is possible but sometimes the cost of that is way too much and it's really not worth it.
But in this case in our DB my greater.
It is possible that someday in the future we may decide to log messages in a file or in a
database as
opposed to a console.
So how can we design this DD migrate such that it's extensible.
Well that's by using an interface.
Let's see how we can make this happen.
So instead of using the console directly here we should use an interface like logger.
Let's create an interface for that first
so public interface.
I logger.
Not that I'm prefixing that with capital I know lugger may provide methods like log error
which gets
a message or another method like log info is for simply logging information messages which
are not for
reporting problems in the code.
It's purely for troubleshooting.
Let's put this interface in a seperate file to clean up our code.
So back here alternate enter enter.
OK now back to the program and I'm going to do the same thing with DB migrator I'm going
to put it in
a separate file so alternate enter enter.
Now we want to change DB migrator to get and I logger interface.
So as we learn in the last lecture we need to create a constructor here and in the constructor
we inject
that interface.
So I lugger the colored logger and with resharpen we can press alternate enter here when the
cursor
is on the logger here and enter again and resharpen automatically create a private read only
field of
type.
I lugger So the technique we are using here is called dependency injection which means in
the constructor
we are specifying the dependencies where it is DB migrator class and later in the main
method as we
will see shortly.
We're going to specify a concrete class that implements that interface.
So this whole thing is called dependency injection.
Now in the migrate method instead of directly talking to the console we're going to talk to a
longer
.
So say logger that log info and I'm going to cut this message here.
And paste it here
except that I need to change it come on to plus because I have to concatenate them to form a
string
.
We're asking the console dot write line.
We were passing multiple arguments.
Let's remove that.
And I'm going to repeat the same thing here.
This time I change started to finished again to refresh wer mind remember the analogy I use
for the
restaurant.
They said the restaurant needs a chef.
Now whether that shift is Jonge or Steve or Mary it doesn't matter as long as that chef has
some capabilities
to a given standard.
It's the exact same scenario here so DPMI greater doesn't care who is the actual logger and
instance
of any class that implements this interface can be passed in the constructor here.
So there is no coupling between DB migrator here and that concrete class.
Now let's create a concrete class that implements that interface.
So the public class let's call it console logger because we use console for logging I lugger
not the red underline that's because we have not implemented the interface yet.
So we press haltered enter and enter.
Now here I'm using resharpen.
So it opens up the dialog box which allows me to choose which methods I would like to
implement.
And by default both of them are checked.
If we don't have resharper I think visual studio automatically implements all methods in the
interface
.
So let's just go with the defaults.
So for long an error I'm just going to use console dot write line and pass that message here
and to
make it a little bit more user friendly.
We can perhaps change the color of the font so say Konsole foreground color equals Konsole
color dot
red to indicate an error.
We can't repeat the same thing in the log in full method and it's sort of using red.
We can use say green.
Now let's put this class in a separate file.
OK let's take one final look at DB migrator.
So look it knows absolutely nothing about the console.
And it's just talking to an interface.
Now let's go to the program in the program.
We're going to create an instance of DB migrator.
So our DB migrator equals new DB migrator in the constructor.
I need to specify a concrete implementation of that.
I love our interface.
In this case we pass a console logger.
And finally we call them migrate method of the DPMI greater let's run the application.
There we go.
We got two messages on the console migrate -iong.
Sorry for the spelling it's migrating started at.
Here is the date time and we had a problem here with the formatting of string.
It doesn't really matter.
And we see the second message migrating finished at the time.
Now let's say the hypothetical scenario is going to happen.
So we decide it's full of luggin messages on the console.
We decide to log them in a file.
Let's see how we can achieve that.
So all we have to do is create a new class Pawlick class lugger.
It implements the I logger interface and repeat the exact same steps here.
So all 10 enter and enter again and again we got this method here.
So let's create a constructor that takes the name of the file.
So the tour area passes better and we press alt and enter and again so we got the private field
here
and in the log error method we need to create a stream writer or writing data to a file.
So News Stream writer know that this class is defined in System done.
Io namespace as we see here.
And because I'm using sharper resharpen automatically either the using namespace for me
here so it makes
wer life much easier.
Mike here now in the constructor or stream writer I need to specify the path.
So I use that private field and the second argument specifies whether we like to append for
that file
of course.
Yes.
Then we can call dot write line method and pass that message here.
There is just one problem here.
The problem is that this stream writer uses a file resource. A file resource is not managed by
CLR
or a Common Language Runtime which means we need to dispose that resource once we
finish using that
.
The easiest way to do that is to wrap this whole block here in a using statement.
So let's see what happens.
I moved this large stream writer inside using.
And then in the using block I move this stream right writer dot write line here.
Basically what happens behind the scene is there is an exception handling mechanism inside
this using
that we're not going to see it's implemented by the compiler.
So if something goes wrong an exception is strong or something the compiler will make sure
to close
the file handle by calling the Dispose method on the stream writer.
Let me share a method here so the stream writer do suppose this method is used or fring
external resources
that are not managed by C-L or when we use the using statement here the using block the
compiler automatically
includes a call to the Dispose method so we don't have to manually do that.
OK one last thing here.
Perhaps it's better idea to add a prefix string here to specify that this is an error because when
working
with a file we don't have colorists like as we did with Konsole so we can't say error plus
message could
potentially include the date time here as well but it doesn't really matter for the purpose of
this
lecture.
Now interestingly we need the exact same code for the log info method here but look we are
duplicating
code and there is a principle called dry or don't repeat werself.
So we can refactor this and make it a little bit better what we can do is we can create a private
method
call it log it gets a message and perhaps get another string like message type.
Let me scroll down so we can see just a little bit better.
And then I'm going to move all this code inside this method instead of using this hard coded
error prefix
here.
I'm going to use message type plus colon and a space and then I'm going to reuse this method
in both
log error and log in for methods.
So there's no code duplication anymore.
So I'm just going to call log past a message and the message type is going to be error.
I would do the exact same thing here with log info.
Now even a better way to do this is to use any anti-immigration.
So we should be familiar with enumerations.
But again I leave that to we as an exercise because I don't want to get too distracted with that
coding
practices in this lecture because we just want to see how we can use interfaces to create
extensibility
points in our application.
So I think for now I should do the job.
Let's put this class in a separate file.
So I put the cursor here Hultin enter and enter.
Good.
Let's review what we have done so far.
So back to our program.
See created a DB migrator and passed a console logger instance his constructor.
And finally here we called the migrate method.
Let's take a look at DB migrator so DB migrator talks to an interface.
It doesn't know what concrete class is going to implement this interface.
It doesn't really care.
Now at this point when we run the application messages are logged on the console.
We can't change the behavior of the application.
We're simply going to the main method and swapping that implementation with a different
implementation
.
So instead of Consta logger I'm going to use file longer specifying path.
So I'm going to use C. Kallen backset backslash.
A logged RTX XTi.
Actually this may throw an exception of my machine because I'm running this in a virtual
machine and
I don't think there is access to the root of C drive so I'm going to change the path to projects
back slash
back slash log dot txt.
Let's run this well that no messages are logged in the console anymore.
Let me go to the file system
.
So C-Drive projects Loek.
We have a log file here.
So in four messages are logged in this file.
We'll see there are four of them because I ran the application twice in the middle of
recording.
So don't worry about that.
There is no bug.
The first one says migration startup migration finished.
And then here we run that application again.
So we got two more messages.
So the interesting thing here is we changed the behavior of our application by simply creating
a new
class as we saw here by logger and simply passing that to this constructor here.
I did not change one line of code in DB2 my greater and this is what we call changing the
behavior by
extending application instead of changing the code in object oriented programming.
This is referred to as open closed principle or OCP which states suffer entities should be open
for
extension but closed for modification.
And in practical terms that means here this class should be closed for modification.
We didn't change anything here but this is open for extension using this extension point.
Now don't think that we always need to use an interface in scenarios like from console to file
system
or from file system to database.
Not necessarily.
That was just a simple example in wer application we might have an application that is
working on
a map like a GPS obligation like Google map and we need to calculate the shortest distance
between
two points.
We can use an interface like Route calculator that finds the shortest path between these two
points
.
Later in the future we may come up with a better algorithm maybe an algorithm that is faster
maybe
an algorithm that knows the traffic conditions or whether Street is one way or two ways.
We can't simply create a new implementation of that interface and inject that to wer class
without
changing the existing code.
Or let's say as another example in wer application we have some kind of encryption Maybe
we have
a class that needs to use an encryption service.
So in that case we can create an interface call or encryptor and create a class that implements
that
interface with a very basic encryption algorithm.
Later in the future we may come up with a better algorithm a better encryption algorithm and
we can
simply change the behavior of wer application by creating a new class that implements that
interface
.
So we've got the point.
Well that's pretty much it for this lecture.
I hope we enjoy it.
And thank we for watching
One of the common misconceptions about interfaces is that they're used to implement
multiple inheritance
in C-sharp and I have seen books videos and blog posts that make such a claim but
unfortunately that
claim is fundamentally wrong.
Interface's got nothing to do with inheritance.
Let's go to Visual Studio and see what they mean by looking at a piece of code.
OK in this project I'm demonstrating the concept of a UI framework so we have a class like
we I control
with a bunch of properties like ID size and top left.
Assuming that each we control like a text box or dropdown list can share these attributes.
It also provides a couple of methods like draw and focus.
It's a very very basic implementation.
Now let's create a class called Text Box public class text box and we can derive it from we I
control
.
So in some languages like C++ a class can have multiple base classes and this is what I refer
to as
multiple inheritance.
So we can have we eye control here and less Or sake of discussion say we can also we heard
from size
.
It doesn't make sense conceptually but just for the example look we immediately get a read
on the line
here because in our class cannot have multiple basic classes.
But what we can do here is to have this text box implement multiple interfaces so we can say
it implements
I Dragonball or I drop them all I know we have to implement these interfaces so often enter
later.
Now I mention that interfaces got nothing to do with inheritance.
Let me clarify that when we use inheritance for example when we do right from we I control
basically
we write all the code once here and then we don't have to type the game that text box
automatically
inherits all that code.
But what about interfaces.
Let's take a look at Idraggable.
That interface doesn't have any code.
It just includes a method declaration.
Same for I drop the ball.
There is no code.
So when we go and implement that interface in a class like a text box we have to type that
method declaration
again and then actually implement it.
So there is no code to inherit.
There is no reusability.
And that's the reason that I explain interfaces got nothing to do with inheritance.
On the surface from a technical point of view yes they look like they are based classes of the
text
box but this is just syntax.
It's fundamentally wrong to say a class inherits from an interface a class implements an
interface because
an interface as we see here is simply a contract.
It's saying that any class that implements this interface should have a method that is public
void and
called drop.
And that's what we type here.
So that's the truth about interfaces and inheritance.
Unfortunately when I started learning about C-Sharp and I came across this topic the book I
read told
me that interfaces are used to implement multiple inheritance and that statement as I
explained was
fundamentally wrong and it took me years to really get it for years.
I was confused and frustrated thinking how can we reuse code by inheriting from these
interfaces.
And the truth is that is not possible there is no code Driggers.
All we are doing is confirming to a contract we're making sure that the public interface of our
class
has the methods or members it has declared in the interface.
So I just wanted to clarify this to we in case we come across some books blog posts or videos
that
claim that interfaces are used for implementing multiple inheritance.
Anyone who says that definitely does not have a deep understanding of interfaces.
Interfaces are used for building loosely coupled extensible and testable applications not for
code reusability
.
What interfaces do provide polymorphic behavior and that's what I'm going explain to we in
the next
lecture.
I hope we enjoyed this lecture and thank we for watching
In the last lecture I explain to we that interface's got nothing to do with inheritance.
But interestingly they do provide polymorphic behavior as we learn in the section about
polymorphism
.
So in this field I'm going to show we how we can use interfaces to achieve polymorphism.
Let's get started.
OK in this project I have got a class called video encoder that is responsible for encoding of
video
.
It has a simple method called encode which gets a video object.
Let's take a look at the video encoder class.
Here is a code method for simplicity.
We don't have to worry about the video encoding logic but what is interesting here is that
once the
video is encoded we use the mail service to send an e-mail to the person who uploaded the
video to our
website.
Let's take a look at the mail service.
So again here to keep things simple we're not worrying about how to send an e-mail.
We just log in a message to the console.
Let's run the application.
So we are simulating that a video was encoded and we sent a notification e-mail to the person
who owned
the video.
Now let's get back to video encoder.
There are a couple of problems with this class.
The first one is this type dependency to mail service which is going to affect the stability of
this
class.
So earlier in the lecture about stability learned that if we want to unit test the class we have to
isolate it.
So instead of using a concrete mail service here it would be better to send an interface in the
constructor
and initialize an email service field here.
But there's just one problem.
There is another problem.
The problem is if tomorrow we decide to have another way to notify the person who owned
the video let's
say send them a text instead of e-mail or maybe both.
Then we have to come back to this method and change it.
Which means every time we change this method the class that contains it has to be
recompiled and redeployed
and any other classes that are dependent on this video coder again has to be recompiled and
redeployed
.
And as I've always said Suffer engineers.
We want to reduce the impact of change in our Soffer.
So earlier in the section I introduced we to the open closed principle of object oriented
programming
.
Just to refresh wer memory.
Open Closed principle or OCP states that Soffer entities should be open for extension or
closed or modification
.
Now we are not going to apply this principle everywhere but there are areas in our system
where we see
there is potential for change like in video and Khoder.
We know that potentially we could send a text message to the user.
Or maybe it would notify them as they are online on the Web site.
So here is an area that is going to be affected as a result of that change.
Now how can we implement open closed principle using an interface here.
Well first of all when we design this class we should not think about mail service.
We should think in abstractions.
We should think when we do in court it does its job.
It needs to send a notification to the user who owns the video how we don't know we don't
know what
kind of notification.
We don't know if it's a mail or text message or a real time notification.
So video encoder should not know about that.
So in this class we need to think of a notification channel as an abstraction and that's where
an interface
comes in because the interface is just a role is a contract.
Again remember the example about a restaurant and a chef a restaurant and the chef.
Anyone who can fulfill that role based on some standards can be a chef for that restaurant.
We don't want the restaurant to be tightly coupled to John or Steve so Same here.
We don't want the video encoder to be tightly coupled to a mailed notification service.
So let's see how we can use an interface to implement open closed principle here.
First we define an interface let's call it.
I notification channel.
Again this is an abstraction.
We're not talking about mail or text or whatever.
Now this is just a notification channel.
We want to send a message to that channel.
So here we need a method like void Sandt which gets the argument type message.
Let me create this class
so I moved this class to a separate file
back to where we were.
And same for notification Channel
8 or so it's a very simple clean interface.
Now mail could be one notification channel or H.M.S. could be another notification channel
so we can
create concrete classes that implement this interface so let's create a new class here.
Mail notification channel implements notification channel
alt and enter.
So for simplicity let's just log a message on the console saying sending mail.
It moved this class to a separate file back to where we were.
Let's create another class that implements this interface this time as a mass notification
channel notification
channel.
Again the same steps implement the interface log and message on the console saying sending
asset mass
.
We put this in a separate file
area so we have one interface with two implementations.
Now let's go to our video encoder class.
So here we no longer need a reference to mail service.
We should think in terms of a notification channel but we could have more than one
notification channel
.
Right.
Because at the same time we may want to send an e-mail and also a text message to the
person who owns
the video.
So what I'm going to do is let's remove this field here.
Basically we need a list of notification channels.
So private read only by a list of I notification channel and let's call them notification
channels.
Now resharpen is detecting that I'm using I-List and that's a generic interface as defined in
system
dot collection dot generic so we can click that or press enter so it as the using statement on
the
top here.
Again if we don't have the sharper We have to manually type that.
Now in the constructor we need to initialize that list.
So let's just initialize it to an empty list.
The list of notification channels.
Now all we need to do here is once the video is encoded we need to iterate over the
notification channels
and notify each of them.
So we do a simple for each for each channel in notification channels channel that send a new
message
.
Right.
So in the video encoder we are not talking about Meltzer's we're not talking about S.M. Yes
we're talking
about abstractions.
I notification channel whoever implements that.
That's none of our business.
We don't code or is not going to be affected.
We can create new implementations of that interface and this class remains unchanged.
So with this we actually have open closed principle.
Our software is open to extensions.
We create new implementations of I know to be Kishan channel and it's close for
modification.
So this class is no longer going to be changed.
Now it's just one step missing here.
We need to tell video encoder about the actual notification channels at runtime.
So how we do that is because this list is defined as private because its implementation detail
of this
class and we don't want to expose it to the outside.
We need to create a method here the public void let's call it register notification channel.
We simply guess.
And I notification channel parameter and call it channel.
All we do here is we add that to our list and add channel.
So this is the method we use from the outside.
Let's go to the program class.
So the main method after re-initialize encoder we call that register notification channel
method and
here repassing a concrete implementation of notification channel.
So new mail notification channel and we repeat that it's time we use a mass notification
channel.
Now let's run the application.
There we go.
We got two messages.
One is sending mail.
One is sending S.N. mess.
And interestingly we can create a new class that implements I notification channel and we
just passed
that here in the main.
And as we saw video encoder is not going to be affected.
Now the interesting thing here is that with interfaces we have a polymorphic behavior.
Let's go to video encoder.
So when we are rating this notification channels list at runtime when we call the Send method
depending
on the runtime type of that notification channel a different method is going to be called.
And that's what we call polymorphism.
So at runtime if the first element of our list is a mail notification channel object the Send
method
in the mail notification Channel class will be called upon Get back here.
Now if the second element of the list is an s.m.m notification channel object a different Send
method
will be called upon.
So as we see with interfaces we can have polymorphic behavior and that's very powerful.
Now there is also a different way to implement the exact same scenario in C-sharp and that is
using
events and delegates.
And that's something that I have classified as advanced topic which we can find in my C-
Sharp advanced
course.
So in my C-Sharp advanced course I introduced we to the concept of delegates.
And I actually have a video on my WeTube channel called events and delegates where I
introduced the
exact same problem but use a different solution using an event and a delegate to implement
that kind
of extensibility.
So in case we're passionate about learning all this stuff that's an additional video we can look
at
.
I hope we enjoy this lecture.
And thank we for watching
ADVANCE
So what is a Delegate?
A Delegate is an object that knows how to call a method or a group of methods.
A simpler way to define that is a Delegate is a reference or a pointer to a function.
Now why do we need something like that?
We can call methods directly.
Why do we need a Delegate that is responsible for calling methods for us?
Well, this technique allows us to create applications that are extensible and flexible.
And often this is used in designing frameworks.
Let me explain this in code.
Here in this project, I have a class of photo that represents a photo or an image.
A Photo Processor, which has one method called Process.
It takes a path to a file, loads the photo,
applies a set of filters like brightness,
contrast, and resizes the photo.
Let's take a look at the Photo Filters.
For simplicity, I have just used Console.WriteLine
because we don't want to get distracted with image processing algorithms here.
But the point here is imagine we're responsible for
designing a framework that is used for processing photos.
This code has a problem. It's not extensible.
What do I mean by that?
Well, look, so far we have applied three filters here.
What if we release this framework,
but another developer wants to use wer framework
and apply a new filter that we haven't defined?
Then the problem is we have to create that filter and recompile and redeploy wer code.
Now imagine if every time a developer in the world needs a filter,
we have to keep compiling and deploying wer code.
This is not a good idea.
So with Delegates, we can make this framework extensible
such that a developer can create their own filters without relying on we.
The same problem can be solved by Interfaces using some kind of polymorphism.
But in this video, I'm going to show we how to use Delegates to achieve this.
Later, I will give we a simple guideline to choose
whether to use Delegates or Interfaces.
So before we change anything in this code,
let's run the application and see what happens.
So we got three messages on the console: applying brightness,
contrast and resizing photo.
How do we use a Delegate to make this extensible?
First, we need to define a Delegate type.
So we start with public Delegate.
When defining Delegate we need to define the signature of the method.
Now this Delegate will be responsible for calling.
So that's a void.
And I'm going to call it PhotoFilterHandler.
It takes a parameter of type Photo and that's it.
So this is the name of our Delegate.
And an instance of that Delegate can hold
a pointer to a function or a group of functions that have the signature.
So they're void and take a parameter of type photo.
Now to make this method extensible,
instead of hard coding this filters here,
I'm going to get rid of that and pass a Delegate to this method.
I'm going to call it here passing our photo object.
What this means is this code does not know what filter will be applied.
And it's the responsibility of the client of this code.
Whoever is using that,
they will define the filters they want,
maybe a developer wants to apply only brightness and contrast,
maybe another developer wants to apply 10 other filters.
It's up to them. This framework does not have to be recompiled and redeployed,
which makes it extensible.
Now, the client of this class is our program.cs.,
and imagine this is the code that we as a developer
or a consumer of that framework is writing.
So here first we have our photo processor instantiated.
Now let's create an instance of that Delegate.
So our Delegate is PhotoProcessor.
I defined it in that class and it's called PhotoFilterHandler.
So filterHandler equals I'm going to point it to a method.
What method? Well, we can start with this PhotoFilters.
Let's assume that this was really with the framework.
So let's say we want that Delegate to point to this method first.
I create an instance of photo filters,
filters equals new PhotoFilters.
Right now my handler which is a Delegate or pointer to a method is going to point to
filters.ApplyBrightness and in our process method
we pass this filterHandler here.
So now if I execute this code, let's see what happens.
We get Apply brightness.
We can easily change this code and apply another filter.
So we get the Delegate here and we use the plus equal operator to add another filter
or another pointer filters.ApplyContrast.
Let's run the application again.
Look now we've got two filters.
And what is interesting is that
if I need a filter that was not released with the framework,
I can create my own here.
Let's say, I would like to create a filter for removing red eye,
static void RemoveRedEyeFilter.
It takes a parameter of photo.
So this method should confirm with the signature we defined here or our Delegate.
So again a Delegate is a pointer to a method with a signature.
I can reprogram. So this is my custom filter.
And here I'm going to type in Console.WriteLine Apply RemoveRedEye.
I can go ahead here and add that to our Delegate.
We'll Remove RedEyeFilter.
Let's run the application.
There we go. We got the new filter here.
So Delegates are very powerful and it allows us to
create applications or frameworks that are extensible and very flexible.
Again we saw that I added this new filter here,
but that class PhotoProcessor was absolutely unchanged.
So was the Photo Filters that were released with the framework.
Now let's get back to our program.
I want to show we what happens under the hood when we create a Delegate.
So I'm going to put a breakpoint here with
F9 and press F5 to run the application in the debug mode.
OK. Let's see I can make this filterHandler variable.
Look it derives from multicast Delegate class.
So every Delegate in.NET that we create with the Delegate keyword is essentially a class.
A class that derives from multicast Delegate. Let's expand that.
So that class multicast Delegate is derived from system to Delegate. Let's expand this.
This Delegate class has two public properties, Method and Target.
Method represents a method that the Delegate is pointing to.
So in this case, we set our Delegates to point to
ApplyBrightness method of Photo Filters class.
So Target is the class.
That holds that method.
Now let's continue execution one line.
So F10. Let's see what happens.
Filter Handler and expand that here.
Because it derives from multicast Delegate that means we
can have pointers to many functions,
which in this case, we have two functions or
two methods ApplyBrightness and ApplyContrast.
Let's take a look. So if I expand multicast Delegate in the nonpublic members,
it has a field called invocation list.
Let's expand that. So it has two methods.
One is ApplyBrightness.
One is ApplyContrast.
So the difference between multicast Delegate here and Delegate is that multicast Delegate
allows us to have multiple function pointers where
as Delegate allows us to have only one function pointer.
So in this case, because we are appending multiple filters,
multiple function pointers to our Delegate,
our Delegate is a multicast Delegate.
OK let me stop the debugger.
OK now we have an understanding of what Delegates are and what we can do with them.
Let's go back to our PhotoProcessor code here.
See here we defined a custom Delegate that points to a method that
returns void and takes a parameter of type Photo.
Instead of creating a custom Delegate,
we could use one of the existing Delegates that come in.NET framework.
In.NET we have two delegates that are generic and they are Action and Func.
Let me show we how they work?
System.Action.
So Action as we see from the icon here is a Delegate.
It comes in two forms.
One is non-generic, and one is generic.
Let's look at this one. Look, it has 16 overloads.
One, that takes only one parameter.
Here is another one that takes two parameters,
three parameters and up to 16 parameters.
So this Action can point to a method that takes any of these parameters.
A method that takes one parameter or up to 16 parameters.
We have another Delegate which is Func. Let's take a look at this one.
The difference between Func and Action is Func points to a method that returns a value,
rather Action points to a method that returns void.
So in this case, look, the first overload of Func specifies
out TResult and that is used to specify the return value from that method.
If our method has one parameter and returns a value we can use
this overload or if our method has
two parameters and returns a value we can use this one.
So all these 16, 17,
maybe 18 overloads gives we a lot of
flexibility which means we don't need to go and create wer custom Delegates.
So let's change our application a little bit.
I'm going to get rid of this PhotoFilterHandler and instead use
the generic Action Delegate.
So in the Process method,
we say we can pass any Delegate
that takes a Photo as an argument and returns void.
Let's run the application. We had an error here which is saying
the type name PhotoFilterHandler does not exist in the type DelegatesPhotoProcessor.
So here I forgot to change that.
Here instead of using the custom Delegate,
we used Action of Photo.
Let's run the application.
All good. So to recap,
a Delegate is a pointer to a function or more
accurately it's an object that knows how to call a method or a group of methods.
We use Delegates to achieve flexibility and extensibility.
Of course, we don't need this all the time,
but if we're designing an application or
a framework where extensibility or flexibility is a concern,
we can use Delegates for that.
Alternatively, we can use Interfaces.
How do we decide whether we need to use
an Interface or a Delegate to achieve flexibility?
Well, part of that is personal preference and different developers have different tastes.
But the guideline in MSDN suggests to use Delegates when we have some kind of
eventing design pattern or the caller doesn't need to access other properties,
methods, or interfaces on the object implementing the method.
In the case of the example I showed we our filters were
just one basic simple method and there were no other properties or methods.
But imagine if our Photo Processor needed to access other properties or methods,
obviously a Delegate wouldn't work and we have to use an Interface.
Well that's it for this video.
I hope we enjoyed it. And thank we for watching.
So lambda expressions.
What are these lambda expressions?
A lambda expression is nothing but an anonymous method.
That is a method that has no access modifier,
like public or private,
and has no name,
and it has no return statement.
Why do we use them?
Why do we use anonymous methods? For convenience.
We can write less code and achieve the same thing,
plus our code would be more readable.
Let me show we this with an example.
Let's say, we would like to write a method that takes
a number and returns a square of that number.
Typically, this is how we would do this.
So static and square and number.
Return number times number,
it'll return the square of that number.
Let's make a call to this method.
First, I put Console.WriteLine(Square),
I'll set five here,
so we should get 25.
Let's run the application with control and F5. There we go.
Now, with lambda expression,
we can achieve the same thing but with less code.
Let me show we how it works.
The syntax for a lambda expression is something like this.
So we have the arguments,
and the lambda operator, and some expression.
Read this as, args goes to some expression here.
For example, if I want to rewrite this method,
using a lambda expression,
this is how I would do this.
So the parameter or the argument is number,
then goes to number times number.
So this is what we call a lambda expression,
and this code is exactly equivalent to this method.
And as we see it's shorter,
I didn't have to specify static,
an access modifier like public private,
and as the return type or as the argument type.
The compiler can automatically infer that in most cases.
And if not, we can explicitly specify that.
I also didn't have to write this return statement here.
So what we need to do is we need to assign that to a delegate.
Remember what a delegate is?
A delegate Is a pointer or reference by a method or a group of methods.
In.NET, we have some built-in delegates that we see all the time.
For example, we have Func<> and Action<>.
Just to refresh wer memory,
let me comment on this a bit.
So Func<> represents a method that takes
zero or more arguments and returns a value of type TResult,
which is generic, as we can see here.
Action<>, on the other side,
is another delegate that takes zero or more arguments and returns void.
In this case, if we want to use a delegate to point2,
this method here we need Func<>.
So we can say, Func of int and int.
The first parameter here,
the first generic parameter here,
represents the argument to the method;
and the second one represents the data type or the return value.
So in this case, because our square method takes an integer and returns an integer,
we use Func of int and int.
So let's give it a name.
This delegate, as we see,
can point to this method without any problems.
Now, what they can do is instead of creating that method here,
I can just use a lambda expression here.
Saying, number goes to number times number and I can call this delegate like this.
Let's run the application.
We get the exact same result 25.
So there is no need to write this method here.
I can just get rid of it, which would be sharper.
As we see it's grayed out,
so I can press Alt and Enter.
And note the first suggestion is "Remove unused method".
So enter, done.
So this is the basic syntax for a lambda expression.
On the left side, we've got the arguments,
the lambda operator, and the expression.
If we don't need any arguments,
we need to write a lambda expression like this goes to, and here is the code.
If we have one argument,
we can use just the argument by itself without using parentheses.
And if we have multiple arguments,
we should always surround them in parentheses (x,
y, and z) goes to blah blah blah.
In terms of scope,
the lambda expression here has access to all the arguments passed,
as well as any variables defined inside the method here,
where we define the lambda expression.
So, let me show we an example.
Let me delete this, I'll create another one.
Let me define a constant,
call it factor, give a value of five.
I want to create a method that takes a number and multiplies that by this factor.
So I can use Func<> delegate,
the input to that function would be an integer,
and it returns an integer.
I call this function or delegate, multiplier,
and I use a lambda expression to say,
"n goes to n times factor."
So as we see, we have no compile-time error here.
This lambda expression perfectly understands this factor,
constant that is defined here,
inside this method, as well as the argument that is passed to it.
So let me call this multiplier.
Multiplier. We had a value of 10,
so we should get 50 in result.
And I can put that on console, so cw, remember?
Code snippet. Tab, result,
and lets run the application.
There we go, we got 50.
So, this is the basic of lambda expression.
But let me show we a more practical and common use case of lambda expressions.
First, let me get rid of everything here.
We're going to work on another example.
Here, I've got a class, called BookRepository.
Let's say this is responsible for returning the list of books from the database.
Now, to keep things simple here,
I have just hardcoded a few book objects in a list.
So, this method here get books,
returns a list of books, and list.
As we see, it's a generic type,
as indicated by angle brackets.
So it's a collection of books.
And here, I am using the object initializer syntax during initialization of the list,
so I can immediately populate that list with a few objects as I instantiate each book.
Again, I'm using the object initializer syntax to quickly initialize the book object.
So we have three books.
Title one, two, three.
The first two are less than $10 as we see,
and the second one is $17.
Let's say, we want to write the code that
returns all the books that are cheaper than $10.
So, let me show we how we would typically do this without a lambda expression,
and then, we'll refactor the code and use a lambda expression instead.
So first, let's get the list of books.
So, at this point, our books variable is of type, list of book.
So here, as we see in the tool tip,
It points to a list of T,
and here note that T is a LambdaExpressions.Book.
Lambda expressions is the name of my solution or project,
so it's a namespace.
Okay, now, let's take a look at this object.
See, here, in the list,
we have these fine methods here that are used for filtering collections.
I'm going to show we how to use FindAll.
Take a look at the argument.
Here, we need a predicate of type book.
What is a predicate?
We see that all the time when working with collections.
A predicate is basically a delegate which
points to a method that gets a book, in this case,
because it's of type of book,
and returns a boolean value specifying if a given condition was satisfied.
Let me show we an example.
So I'm going to create a predicate function.
Let's call it IsCheaperThan10Dollars.
I pass a book here,
and I return True if book.Price is less than $10.
So this is what we call a predicate method.
It gets an object of type book,
and returns True if a given condition is satisfied.
All these Find methods here,
they accept a predicate.
Look, so, what happens when I call this method and pass a delegate of type predicate?
Which means a method like this,
I can pass that here,
is cheaper than $10.
What happens is, the code inside this method,
well iterate the collection,
and for each book,
it will pass that book to this method to determine if the condition is satisfied.
If yes, then it will return that book in the list of results.
So, with that code,
I can say, cheapBooks equals to that.
And let's iterate that to our collection.
It should be cheapBooks.
And let's put that on the console.
So I'm going to display the title of the book.
Let's run this application.
So we got Title one and Title two,
and back to our BookRepository,
note that all of these are under $10. So the code is working.
Now let's see how we can change this code and use a lambda expression.
See the problem here is every time we want to call this Find or any of its variations,
we have to go and create a method like this,
and while this is perfectly fine we can achieve this with less code.
So why not? So here,
all we have to do is to say,
book goes to book.Price is less than 10.
So, this lambda expression is exactly equivalent to this method here.
And with ReSharper installed in my Visual Studio,
we can see that now this method is grayed out,
which means it's not used.
So what I can do is to put my cursor on the method name here,
and we get this triangle here.
I can press Alt and Enter.
And the first suggestion is to remove unused method.
So I press Enter,
and that code is gone.
So again this is a lambda expression.
On the left, we've got the argument,
and on the right side, we've got the actual expression.
And this is what we call a lambda operator.
We read this expression like this,
book goes to book.Price is less than $10.
In C#, it's pretty common
to use a single letter when defining lambda expression arguments.
So in this case, because we are working on books, it's obvious.
So, we can just use b.
See, the code is even shorter now.
Well, that's it for this video.
I hope we enjoy it, and thank we for watching.
Hello everyone. welcome to programming with Mosh.
My name is Mosh Hamedani and in this video,
I'm going to talk about events and delegates in C#.
I have noticed that a lot of developers starting with C#,
find the concept of events and delegates a little bit confusing.
In fact, I was one of them when I was starting out.
So, I decided to create this video for we and I hope,
by the end of watching this video,
we will have a good and in-depth understanding of events and delegates,
why we need them, how to use them, and how to create them.
So let's get started.
So, what are events and why do we need them?
Well, events is a mechanism for communication between objects.
That means when something happens inside an object,
it can notify other objects about that. Why do we need that?
Because it can help building loosely coupled applications.
What is loosely coupled applications?
That means an application,
that its components or classes are not tightly coupled together.
A loosely coupled application is easy to extend without
breaking or changing one or more of its existing capabilities.
Let me show we an example of this in the code.
So take a look at this class.
This is a video encoder class with one method,
called encode, which encodes the video that is passed to it.
For simplicity, I've gotten rid of the encoding logic, but look at the last line.
Here, when the encoding is finished,
we use the mail service to send a mail message to the person that owns the video.
Now, there is nothing wrong with this code,
but let's say, in the future,
there is a scenario and we may want to send a text message to the video owner.
So what we need to do is to go ahead and add this extra line of code to this method.
Now, again, this is for simplicity.
In a real world scenario,
it could be a few more lines of code.
Now, the problem here is,
because we add this extra line of code here,
that encode method is changed,
which means it has to be recompiled,
which means the video encoder class also has to be recompiled,
which means any other classes that are
dependent on this video encoder have to be recompiled and redeployed.
So, as software engineers,
we want to reduce this problem.
We want to design our application such that when we want to change the application,
that change has minimal impact on the overall application.
The problem here with this code is that,
by adding an extra line,
we may accidentally break something along the way.
Now we can use events to resolve this problem.
Take a look at this picture here.
We can have our video encoder class to publish an event called VideoEncoded,
and have the MailService class to subscribe to that.
In this case, we refer to VideoEncoder as a publisher or an event sender,
and MailService is a subscriber or an event receiver.
Now, what is interesting about this picture?
That VideoEncoder knows absolutely nothing about MailService,
which means, in the future,
if we want to extend our application and add
the capability to send a text message when the video is encoded,
we can simply create a new class, called a MessageService,
and have it subscribe to that VideoEncoded event of the VideoEncoder.
So basically, the VideoEncoder does not need to be recompiled and redeployed,
and we simply extend the application by adding a new
class-- so this reduces the impact on the application.
Ideally, if we could extend our applications by simply adding new classes,
the compilation time would be reduced and
application could be redeployed without breaking things along the way.
Now, let's take a look at what the code would look like if we want to
implement this eventing mechanism between these classes.
So here is our VideoEncoder class again.
We have the encode method as before,
with the encoding logic at the end.
Instead of directly making a call to the MailService,
which we had before, we simply call a method called OnVideoEncoded.
Don't worry about that method,
I'll cover it shortly,
but the purpose of this method is to simply notify the subscribers.
VideoEncoder knows absolutely nothing about the MailService or the MessageService;
they can come later and we can add
more subscribers without changing anything in this code.
Now back to our picture, we might be wondering.
How does the VideoEncoder notify its subscribers?
Well, for video encoder to notify its subscribers,
it needs to send a message to them.
In practical C# terms,
that means invoking a method in the subscriber.
But how does the video coder know what method to call?
For that to happen,
we need an agreement or a contract between these publishers and subscribers.
So this agreement is something that both the publisher and subscriber agree upon.
That is a method with a specific signature. Take a look at this method.
So this method is void.
It has two parameters,
which the first one is an object and the second one is an EventArgs,
and this is a very typical implementation of a method in the subscriber.
We often call these methods event handlers and that's the method that
is called by the publisher when the event is raised.
So that means, back in our picture here,
we need to have a method like that in MailService and MessageService.
So, when the VideoEncoder wants to raise that event,
it's going to call these methods.
Now, I need to clarify something here.
Again, VideoEncoder does not know about the existence of MailService or Message Service.
It knows absolutely nothing about them.
It's decoupled from them.
All it knows is a method, nothing else.
Now, how do we tell VideoEncoder what method to call?
That's when a delegate comes in.
So, a delegate is basically an agreement or a contract between publisher and
subscriber and it determines the signature of the event handler method in the subscriber.
So, back in our picture here,
we can have a delegate that determines when a video is
encoded and we want to notify subscribers,
we should have a method that is void with these parameters.
The name doesn't matter but the signature is important.
So now that we have a basic understanding of events and delegates,
let's take a look at a piece of code and see how to create an event and a delegate.
So, here I've created a very simple console application.
Let me walk we through the classes we've got here.
First, we've got a video class which is a very basic class with
a simple property for the title of that video.
We also have that video encoder that we saw earlier in the slides.
So it has one encode method that gets the video.
First, it logs a message on the console saying we are encoding
the video and just to simulate an encoding process,
I used thread.Sleep to delay the application for a period of three seconds.
In the program.cs, in the main method,
first we instantiate the video here,
then we instantiate the video encoder and finally we call the encode method,
passing the video object.
So, very basic. Let me run the application now so we control and f5.
Okay, we got the message Encoding Video, and notice,
there was a three second delay before we saw the,
Press any key to continue. Let me run it again.
So waiting one, two,
three. There we go.
Okay, now, we want to implement an event
in the video encoder such that when the encoding is finished,
it notifies anyone who is interested in that event.
Now, to give this class the ability to publish an event,
there are three steps we need to follow.
First, we need to define a delegate,
that is, the contract or the agreement between the publisher and the subscriber.
So, a delegate determines the signature of
the method and the subscriber that will be called when the publisher,
in this case video encoder, publishes an event.
Second, we need to define an event based on that delegate.
And third, we need to raise or publish the event.
So, let's go ahead and implement each of these steps here.
To define or declare a delegate,
we start with public because we want it to be accessible
anywhere and we use the key word 'delegate'.
Now, imagine we're declaring a method.
To declare a method,
we need to specify the return type,
give it a name and parameters.
And this method will be actually the event handler and the subscribers.
So, if I want to declare an event,
I would say void or give it a name, VideoEncodedEventHandler,
then parameters typically in.NET,
we have this convention that we want the first parameter of the event handler to be
an object and that is the source of
the event or the class that is publishing or sending the event.
And the second parameter is in EventArgs,
which is basically any additional data we want to send when the event.
So, let's review up to this point.
We are declaring a delegate,
which actually holds a reference to a function that looks like this.
So that function or method is void.
It has two parameters.
The first one, typically in.NET should be of
type object which is the source of the event.
And the second parameter is EventArgs,
which includes any additional data about the event.
Now, how did it come up with this name?
In.NET we have this convention and we say
if the name of our event is going to be VideoEncoded,
we use that and then append EventHandler as the name of the delegate.
So that is our first step, define a delegate.
Now we need to define an event based on that delegate.
So we start with public event.
This event should be based on that delegate.
So we use VideoEncodedEventHandler,
and give it a name.
So VideoEncoded.
Note that I use the past tense form here
to indicate that something has happened and finished.
Sometimes in.NET we may see an event referring to present tense like SameVideoEncoding.
In that case that event should be fired or
published before the encoding is finished, sorry, started.
So here we just use the past tense.
So the second step is done with define
an event called VideoEncoded, based on that delegate.
And the third step is to raise the event.
To raise an event we need a method that is responsible for that.
Let me create that here.
So in.NET again, there is a convention -.NET Framework
suggests that wer event publisher methods should be protected.
They should be virtual and void.
And in terms of naming,
they should start with the word on and then the name of the event, which is VideoEncoded.
So here in our encode method,
once the encoding is finished here,
we just need to call this method and
we're assuming this method will notify all the subscribers.
So how do we notify subscribers?
That is the responsibility of this method.
We start with checking if there are any subscribers to this event.
So we say VideoEncoded, if it's not null,
now we need to treat this as a method call,
that is, imagine we're making a method call here, so VideoEncoded.
To call methods we use brackets.
Now this method look at the parameters,
object source and EventArgs args.
That's the signature that we defined earlier here, all right?
So what is the source of the event or who is publishing the event?
The current class, or the current object, which is this.
And do we want to send any additional data with that event?
I would say for now just to keep things simple, I would say no.
So whenever we don't want to send any additional data, we use EventArgs.Empty.
This is a static property of this class which
returns an instance of EventArgs which is empty.
Later in the next step,
I will show we how we can send the actual video that was encoded.
So let's review the steps we have done.
First we defined a delegate which is here,
which determines the shape or the signature of the method in the subscriber.
Then the second step was to create an event based on that delegate.
So we defined the event here.
We are saying this event is called VideoEncoded,
and whenever we raise that we want
a subscriber with a method that confirms to this delegate, would be called.
And the third step is raising the event.
So in our encode method,
once we are done we call this method which by
convention should start with the word On and then the name of the event.
And it should be protected, virtual void OnVideoEncoded.
Inside this method we'll look at that event and if there are any subscribers there,
which means it shouldn't be null,
we're going to call them passing the reference to VideoEncoder and no additional data.
Now we are done here.
Let's go ahead and create a couple of subscribers.
So I'm going to go to program here.
Let me create a new class here, MailService.
So this class is responsible for sending an e-mail once the video is encoded.
Now I told we that back in our VideoEncoder,
when we defined this delegate I said we need
a method that confirms with that signature and the subscribers.
That method should be void and have these two parameters.
So let's go ahead in our Program.cs here,
in our MailService, create a method.
This is the event handler.
So that method should be void.
We're going to call it OnVideoEncoded.
We should have two parameters,
object source EventArgs e, right?
Now in this case we don't want to send an actual mail.
I just want to simulate that.
So we want to write a message to the console.
I'll show we a quick tip here. Just type cw.
That's a code snippet. If we press tab,
that just writes Console.WriteLine.
It's a way for we to quickly write code.
I have a course on Udemy called Visual Studio Tips and Tricks,
or Double Wer Coding Speed and in that course,
I teach we a lot of code snippets and various techniques to help we write code faster.
So in case we're interested the link is on the screen here. All right let's move on.
So when this method is called we want to log a message to the console saying okay,
we are in MailService sending an e-mail.
That's pretty much it. Now what we need to do is to subscribe
this mail service to the video encoded event of VideoEncoder.
So here in the main method we have the video,
we have the VideoEncoder, which is the publisher.
So that's going to be the publisher.
Let me create an instance of MailService,
MailService and this is going to be my subscriber, subscriber, right.
Now, before we call the encode method we need to do the subscription. How do we do that?
It's very simple. So we start with the publisher "VideoEncoder."
- look at this icon - that's an event, VideoEncoded.
So we are interested in that.
Now the notation is we use
the "+=" operator that is to register a handler for that event.
Who's the handler?
This method in the MailService,
this method in the MailService.
So I put that here,
MailService.OnVideoEncoded,
and semicolon.
Note that I'm not making a call to this method here so I don't have brackets here.
I just use the name of the method and basically what that means
is this is a reference or a pointer to that method.
So VideoEncoded event behind the scene is a list of pointers to methods.
When the video encoder wants to publish that event,
VideoEncoded, it looks at that list, here.
Here we look at that list, and if it's not empty,
that means someone has subscribed to that event which means we have
a pointer to an event handler method and then we're going to call that like this.
That's just the syntax in C#.
So let's get back to our Program.cs.
So note that again we need to do the subscription before calling the encode method,
otherwise the subscriber wouldn't be notified about the event.
Now let's run the application and see what happens.
So we got the Encoding Video which comes from the publisher and
then our MailService was notified and is trying to send an email.
Now let's look at some more interesting stuff here.
First of all I want to move this class to a separate file.
The slow way of doing that is to go here,
copy these and then go,
Solution Explorer, Create a new file and paste. It's not a good way.
What is a faster way?
There is a plugin called Resharper,
which is one of my absolute favorite plugins for Visual Studio.
With Resharper, we get this icon here,
and see, it's suggesting to move this to another file.
All we do is, we put the cursor here on the class name and then press alt and
enter and again we get the suggestions here, then press enter.
That's it. Resharper moved
that mail service class to a separate file which is MailService,
and added that to my solution here.
So Resharper really speeds up wer coding.
Again I explain this stuff in my Visual Studio course on Udemy,
so in case we're interested have a look at that course and we're going to love it.
Back in our program,
now let's create a subscriber that is responsible for sending a text message.
So I'm going to create another class saying MessageService,
and again, we want an event handler method here.
What is the signature of that method?
Should be public void OnVideoEncoded.
The first parameter should be object source,
and the second should be EventArgs args.
Again we want to simulate a texting scenario.
So just use cw Console.WriteLine,
press tab. There we go.
So we are in MessageService now,
"Sending a text message..." And then I go here,
alt and enter, and enter,
move that class to a separate file.
Now we can press control and hyphen to get back to where we were,
which is the program class.
So similarly, with NetPublisher and the subscriber,
now we can add a new subscriber,
var MessageService equals new MessageService.
So here is another subscriber.
By the way these comments is purely for educational purpose.
I'm not suggesting we to write comments like that in wer production code.
Okay, so we've got an instance of the MessageService.
We need to subscribe to the event just like before.
So who is the publisher?
VideoEncoder. What event are we interested in?
VideoEncoded. How do we subscribe?
Plus equal, now MessageService.OnVideoEncoded.
And again I'm not making a message call so there are no brackets here,
just a reference or a pointer.
Let's run the application again.
Look, we got the Encoding Video message which comes from the video encoder.
Then MailService was notified.
It's trying to send an email,
and also MessageService was notified,
and here it's trying to send a text message.
Now the beauty of this approach is
when I created a new subscriber which was MessageService,
did I change anything in the VideoEncoder?
Let's go here. My video encoder is exactly the same.
I didn't even make one line change,
and that's what I was telling we in the slides earlier.
So with events we can create
a publisher and we can add subscribers without changing the publisher.
So this code doesn't need recompilation and doesn't need to be redeployed.
And basically I can extend the application,
add more capabilities by simply creating a new class,
like in this case, MessageService.
Tomorrow we can have a new class,
call it, I don't know,
PagerService that sends a notification using a pager and nothing will be affected.
Now take a look at the VideoEncoder here.
Here we have a delegate which actually it's a reference to method,
or the event handler.
That method should be void and with these two parameters.
Now we want to send a reference to the video,
so the subscriber knows which video we encoded.
To do that instead of using EventArgs we need a custom class.
That custom class should derive from EventArgs and
include any additional data that we would like to send to our subscribers.
So let's go ahead and create that, and go here.
I call it VideoEventArgs because
it's a class that contains the data about the video that was encoded,
so it should derive from EventArgs.
Here we need to create a property that determines the video that was encoded.
So quick way of writing that is we type prop and then press tab.
This is a code snippet.
So now I specified the return type which is
video and the name I press tab again and enter, that's it.
So now we can change our delegate here instead of sending EvenArgs,
we send VideoEvent Args,
which means, here, see we got an error,
because when we are publishing an event we are sending EventArgs that empty whereas,
our delegate now expects a VideoEventArgs object.
So I'm going to go ahead and modify this.
We need to instantiate a VideoEventArgs.
And we also need to send a video, video equals,
but where is the video?
We don't have it here. But look,
in the encode video, I'm sorry,
in the encode method, when we encode
the video here we have a reference to the video object.
So we can simply pass that object to this method.
And of course we need to go ahead and change this.
But with Resharper, I can just press alt and enter and
see Resharper is suggesting to add that video parameter to this method.
So I just go ahead and there we go.
Now in the event publisher method,
we've got a reference to the video and I can just put that here.
So with this change now our publisher is going to
send some additional data which is encapsulated in that class,
VideoEvenArgs, and there we'll have a reference to the video that was encoded.
Now let's go to MailService.
We need to change this method to comply with that delegate.
So instead of EventArgs we want VideoEventArgs, right?
And then now what we can do here,
we can just we can output the title of the video.
So I would say "e.",
and put the video object here, ".title".
We need to make the same change in MessageService.
Now a quick way to find that class instead of going into
tabs or in the Solution Explorer is
just with Resharper type control t. And then type of MessageService.
There we go. We are in that class now.
So I'm going to go here and change this to
VideoEvenArgs and when outputting the message I'm also going to add args.Video.Title.
That's it.
Let's compile and run the application with control and F5.
Okay, note that here when MailService was notified,
now we got the title of the video.
So this is a way to pass data about the events that happened.
Okay, the next step is to show
we a simpler way to achieve the same thing with writing less code.
So let's go to our video encoder which is the publisher.
See, we created this delegate here and
specified these parameters as the arguments of the event handler method.
Now what they have done in.NET,
I think it came with.NET Framework Version 2.0 or 3.0,
to make our life easier, they said, okay,
we don't have to go and create a new delegate every time we want to declare an event.
So in.NET they have a delegate type which is
called EventHandler and it comes in two forms.
One is just a normal form and one is a generic form which looks like this.
What this means is they have done the hard work.
So we can use that delegate instead of creating our own,
which means in this case when we are declaring
that event instead of creating a custom delegate like that,
we can just use the EventHandler delegate.
Note the icon here. I think it's a suitcase,
looks like they're... we are delegating it to,
I don't know, what it is called an English, solicitor, lawyer.
I don't know. So that event handler type is generic as we see here.
Now what do we want to send as additional data with the event?
VideoEventArgs.
Now that basically is exactly equivalent to this.
So we don't have to create a delegate explicitly.
We can just use this class here which is a delegate.
So I get rid of this.
Now if we want to publish an event without sending
any additional data instead of using a generic form like this,
we could just use the normal form, like this.
VideoEncoded, now this is complaining because of the duplicate name,
let's just use VideoEncoding.
In that case, that means a method that gets object source as the first parameter,
and EventArgs as the second parameter.
We don't really need it here.
Okay, with that change,
let's compile the application and run it.
Everything working as before.
Well I hope at this point we have a good and in-depth understanding of
events and delegates and how they help building loosely coupled applications.
We saw how we can use events to make our applications extensible and we
also saw how to create
a delegate and an event as well as raising and subscribing to events.
We also saw how we can use the event handler delegates that
comes in the.NET Framework which saves us from creating our own delegate.
So that delegate keyword that we saw earlier,
I just wrote it because I wanted we to know what's exactly happening behind the scene.
That came in the first version of.NET.
But then this event handler class came,
or delegate came and we don't really need to create our own delegates.
I honestly, I haven't seen a used case for that over
the past 12 years of me coding in.Net.
Okay, that's it for this video.
I hope we enjoyed this.
And thank we for watching.
So, we go to LINQ.
What is this LINQ that everybody talks about?
LINQ is one of my absolute features of C#.
It stands for Language Integrated Query and it
gives the capability to query objects in C# natively.
So with LINQ, we can query objects in memory like.NET collections,
we can query databases,
we can query XML and we can query ADO.NET data sets.
Querying.NET collections or objects in the memory is
often referred to as LINQ to Objects.
Querying databases is often referred to as LINQ to Entities.
Querying XML is often referred to as LINQ to XML and
querying ADO.NET data sets is referred to as LINQ to Data sets.
Now this is a comprehensive topic and is beyond the scope of this video.
Especially LINQ to Entities, which is,
use in Entity Framework is a big topic,
and it needs its own course.
I'm actually planning on releasing a good comprehensive course on Entity Framework.
So, if we're interested,
make sure to stay tuned.
Now, in this video I'm going to show we the basics of LINQ,
and get we started.
I'm going to cover a lot of ground,
so we have a good understanding of LINQ,
and what problems it resolves.
So, let's jump into code.
Here in this project, I've got a simple book class with two properties,
string Title and float Price.
I also have this BookRepository,
which has one method called GetBooks,
which returns an IENumerable of Book.
Basically, I have a hard-coded,
a few book objects here in the list.
So here, I'm returning a new list.
This is a generic list of books.
I'm using the object initializer syntax here,
to immediately initialize this list.
And then here, I'm adding a new book, again,
using the object initializer syntax,
to immediately initialize a book.
So as we see our books here have-- Title and a Price.
Let's look at our Program.cs in the main method.
We simply instantiate the BookRepository called the GetBooks method and get the results.
Now, let's see what we can do with LINQ.
Let's say, we want to display the list of books that are cheaper than $10.
If we didn't have LINQ,
this is what we had to do.
We would have to create a new list.
We would have to iterate the books collection and then say,
if book.Prize is less than $10 added to CheapBooks collection and finally,
at this point we have the list of CheapBooks.
So here we could iterate this collection
and display each book title plus its price.
So let's run this code.
So these are the books that are cheaper than $10.
Now, with LINQ, we can get rid of
this piece of code here and do it with one line of code.
So how?
All we have to do is to say "var CheapBooks = books.".
Take a look at these methods here.
These are extension methods and we should be familiar with extension methods.
So if we skipped that video,
make sure to watch it first and here we see that
these extension methods are defined in the namespace here, LINQ.
So let me show we a method here,
where, we use where to filter collections.
Here I'm using ReSharper and as soon as I use the Where method here,
ReSharper immediately added a reference to system that link for me.
If we're not using ReSharper,
we have to manually add the reference here.
Now let's take a close look at the Where method.
The Where method takes a Func of Book and bool.
Remember Func, it's a delegate.
It points to a method that gets a book as an argument and returns a boolean value,
and this is what we call a predicate.
So the general predicate is to get a book,
assess some condition and if the condition is
true returns that book such that it will be added to the output.
So, whatever we see Func as a delegate,
we can use a lambda expression.
Remember lambda expression?
If we'll skip that video, make sure to watch it.
So a lambda expression is a way to write
an anonymous method and that can be assigned to a delegate like Func here.
So here, I will write to lambda expression.
Like b goes to b.Price is less than $10 (b => b.Price <10).
So just to refresh wer memory,
on the left side of the lambda operator we have
argument and on the right side we have the actual expression.
So this is like an anonymous method, that gets b,
which is a book as an argument and executes this condition here.
But it's more accurate to say evaluates this condition.
So if the condition is true,
that book will be added to the list of filtered books,
which will be CheapBooks.
So with this line of code, we can easily get the list of books that are less than $10.
That's from the application.
There we go, we got the same list of books.
Now, let me show we another method here.
LINQ also has a method called OrderBy and OrderByDescending,
and this is used for sorting collections.
This method gets an argument of type,
Func of Book and TKey (Func , which is generic.
So again, this is a delegate that takes a book and then here we need
to specify the property of the book on which we would like to sort the collection.
So, I can write a lambda expression here saying b.Title,
assort them by Title.
Now what we can do here,
which is extremely powerful is we can chain these LINQ methods.
So here, I can put OrderBy right after Where.
In this case, I am filtering the list of books here and then ordering them by Title.
Let's run the application again.
Note that the list is now sorted by Title.
LINQ also has another powerful method and it's called select,
and select is used for projections or transformations.
Let's say, we want to iterate the list of books
and for each book we will like to convert it to
another object or maybe we would just like to select one of its properties as a string.
Let's say, we get a book and select its Title.
So here, if we call this method,
the result here if we hover over var.
Look, the result is an IEnumberable of T and T is a string.
So with Select here,
we are converting a list of books which have been previously filtered and sorted.
We are converting that to the list of
strings because we are only selecting the Title of the book.
So now that we iterate this CheapBooks collection,
we don't have this Title and Price properties anymore because book is now a string.
So let me comment this out, Console WriteLine book.
Let's run the application.
So we just got the Title of the books.
Now in building real world applications sometimes
the lambda expressions we write here get a little bit complex.
So there is a common convention to lay out
wer LINQ method here and that is to lay them out like this.
This way it's more readable and cleaner.
So we filter, we sort, and select the property.
Now this syntax is what we call LINQ Extension Methods.
We also have another syntax to write LINQ queries and that's what we
call LINQ Query Operators (Query Operators).
I'm going to write the exact same code,
but using a LINQ Query Operator.
So I'm going to call this one CheaperBooks.
This is how we write it, from b in books,
where b that price is less than 10, order by b.
Title and select b.Title.
So these two are exactly equivalent.
LINQ Query Operators always start with the From and always finish with the Select.
So here from we are saying from b,
that's like an argument in books.
Now we filter by b.Price,
we order them by b.Title and then finally,
we select b.Title or we could just return the actual book object.
In this case, we will get a list of books.
If I hover my mouse here.
We see, we get an IOrderedEnumerable of TElements and TElement is Linq.Book.
Which syntax we use is I would say purely personal choice.
In terms of power and flexibility this syntax is more powerful
because internally all these keywords translate to this extension methods here.
And we'll find that in more complex scenarios.
There are not keywords for every extension methods that we have here.
But also in other scenarios like when we are doing it GroupBy or Grouping lists.
I think this syntax is more friendly and cleaner.
So there is no right or wrong.
It really depends on the situation and on wer personal choice.
Now for the rest of this video,
I'm going to just stick to LINQ Extension Methods and show we
some really cool extension methods that make wer life much easier.
So I'm going to get rid of this stuff here,
actually I will delete this here as well.
We'll look at more examples in a second.
So let's take a look at our list here.
Here we have a book called ASP.NET MVC.
Let's say, we want to return only that book.
Where method we have seen so far returns a list of books and IEnumerable,
but if we want only a single object in the result,
that's when we use the Single method.
So Single as pretty much the same argument as the Where.
It gets a function of Book and bool,
which is a delegate and we can use the lambda expression here.
So I would say give me the book whose Title is ASP.NET
MVC and I call it here book.
Let's put that on the console, book.Title.
Let's run this. So here is our book.
Now let's see what happens if I add something here,
but obviously we don't have a book by that name.
When I run this, the application crashed.
We got an unhandled exception,
Invalid operation exception, Sequence contains no matching element.
This is one of the errors that we see a lot when working with LINQ.
So, Single method expects that there must be
one and only one object in wer collection that satisfies this condition.
Now, if we're not sure if that object exist or not,
we can use SingleOrDefault.
The difference is, if there are no objects matching this condition,
Default will be returned,
which in this case would be null.
So, ny book object here will be null and I cannot access the Title property.
Let me just show we that book is null,
is true. Let's run this.
There we go-- the book is null.
We also have a few other similar methods to Single,
one of them is First.
Now first is used to get the first object in a collection.
Optionally, we can supply a predicate, the filter.
Say give me the first book whos title is... let's
say C# advanced topics.
Let's take a look at our BookRepository here.
So we have two books called C# advanced topics,
and I want to get the first one.
So, I use the first method here and here let me uncomment this,
and also at the price of the book.
Now let's run the application.
So we got the book that is called C# advanced topics and it's $7.
Let's look at our BookRepository.
See we have two books here and the first one is $7.
Similarly, we also have a FirstOrDefault and this is similar to SingleOrDefault.
So if there are no books that match this condition.
This method returns NULL instead of throwing an exception.
We also have a method called Last or LastOrDefault,
and we should guess what they do. So let's try this one.
Let's run this. So in this case,
I got the book-- that is $9.
And other useful link extension method is...
Skip and Take.
What are these?
These are used for paging data.
So with Skip we're saying,
skip two records or two objects and take three.
Let's see if it actually works,
because here I've got one,
two, three, four, five.
That's fine. So, It's going to skip the first two and return the next three.
So let's run the application.
Now this method returns an IEnumerable of book.
So this should be books.. and I would..
Whoops sorry the name is conflicting with this books here.
So I'm going to call this pagedBooks.
And I would iterate the collection,
pagedBooks and put that pagedBook Title on the screen.
Let's run this. So we got the ASP.NET Web API,
as well as C# Advance Topics.
Let's double check.
So, we skipped two objects here and we got three objects.
So Skip and Take are pretty useful.
We also have a bunch of aggregate functions like we have in SQL.
For example, let's say we would like to count the number of books,
and of course this is not going to be pagedbooks,
it's going to be count.
And let's just put that on the console,
but we have totally five books.
We also have a useful method here called Max.
Which is used to return an object that as assumed max of something in a collection.
So in the list of books, what does Max mean?
We kind have to give it a meaning.
In this case, they can look at them.
Arguments, we can pass a delegate that takes a book and returns some value here.
Bu what I can do is,
say return a book that has the highest price.
Let's run the application.
That's $12. Well, count is not a good name.
At Max method, is returning actually the price,
the highest price, not the book that has the highest price.
So that would, that should be called Maximum price.
Similarly, we can have minimum price.
Tell me how much is the cheapest Book.
Sorry, I forgot to put that on the console.
So this one is going to be minimum price.
So a minimum price is $5.
So Max, Min, Count and we also have Sum.
Let's say we would like to sum this collection based on the price of books,
and we call this perhaps,
TotalPrices which actually doesn't make
sense in this case but I'm showing we as an example.
So, the sum is $42 and 99¢.
So what I wanted we to learn in this video were these extension methods here.
Books.Where to filter and return a list of books that match a given condition.
Or we can use Single to return only a single book that matches a given condition.
Or SingleOrDefault which is safer to use because single,
if it cannot find any books that matches the given condition it throws an exception.
Whereas, SingleOrDefault returns none.
So these are for filtering.
We also have the First,
as well as FirstOrDefault which is safer.
We also have Last,
as well as LastOrDefault.
We also have a bunch of aggregate functions, like Min,
like Max, like Count, like Sum.
I think we even have an Average, there we go.
So we can pass a delegate,
say give me the average of the price.
We also have useful methods here.
Skip and Take, which is used for paging.
Now, the beauty of LINQ is whether we're quering objects
into memory or we're quering XML or we're quering database,
we keep using LINQ like this.
We don't have to learn Xquery to query XML,
or we don't have to learn Transact-SQL to create databases.
Well, it's good to know SQL or programming databases, but in general,
we can use LINQ in a lot of cases and what LINQ does for we or what Entity Framework
does more precisely is it takes this LINQ extension methods and when we call them,
it translates them to SQL query.
So we never have to go and create a story procedure.
Again, this is a very comprehensive topic and it's beyond the scope of this video.
Hopefully, I will release my Entity Framework Course soon,
and there, I will explain all of these amazing things that we can do with LINQ.
I hope this video gives we a good foundation to start with LINQ.
See what benefits we get and as we prepare for real world applications.
I hope we enjoyed it and thank we for watching.
Okay, Dynamics.
Dynamics is one of the features of C# that sometimes confuses some developers,
but it's actually pretty easy.
Let me give we some background information.
Programming languages are divided into two types —
statically-typed languages and dynamically-typed languages.
Or in short, we can say static languages or dynamic languages.
Examples of static languages are C# and Java.
Dynamic languages are like Ruby,
Javascript, Python, and so on.
But what's the difference?
The difference is in static languages — resolution of types,
members, properties, methods is done at compile-time.
So if we try to access a method that is not defined in an object,
when we compile the application,
we are getting an immediate feedback that's telling us
that method or property is not found on that object.
With dynamic languages — the resolution of types,
properties, members, methods is done at run-time.
But what's the benefit of that?
First, I'm not an expert in programming languages,
but based on my understanding,
dynamic languages are a little bit easier and faster to write code with.
But on the flip side,
because we lose compile-time checking,
we have to write more unit tests to make
sure the application behaves properly at run-time.
Now, C# started as a static language,
but in.NET Framework version four,
they added dynamic capability to it,
and the intention was to improve interoperability with
COM or dynamic languages in.NET like IronPython.
If we're writing code for Microsoft Office applications such as Word or Excel,
dynamic is a feature that is going to help we a lot.
Without dynamics, we have to use reflection.
What is reflection?
Reflection is a way to inspect the metadata about the type,
and access properties and methods.
Let me show we an example.
Let's say, I have an object here.
Give it a name of "obj" and assign it to a string, my name.
I can call the GetHashCode method here,
like this, and that's pretty easy.
But with reflection, if I want to call that method,
my code will end up looking like this.
First, I get the type of that object.
And then, I get a reference to a method,
called GetHashCode, and that returns a methodInfo object.
Now, I can invoke methodInfo,
like this and pass some weird arguments here.
As we see it, this code is not very beautiful.
So reflection is a little bit difficult and messy.
The benefit of dynamic is that,
let's say, we're getting an Excel object,
and we know that that object should have some method called, I don't know,
let's call it — let's define an object here, excelObject.
I set it to a string for now,
just for simplicity because I really don't have Excel objects here.
And let's say, we know, I'd run-time that object,
should have a method called, Optimize, for example.
We see that we get compile-time error,
because the object class here does not have a method called Optimize.
With dynamic, we can easily resolve this problem without having to use reflection.
With reflection, our code would end up like this,
whereas with dynamic, it looks like this — it's much cleaner.
So that's how we use dynamics in C#.
But how does all the magic happen,
as in resolving types,
properties, members at run-time?
We should be familiar with CLR or Common Language Runtime.
It's.NET's virtual machine that gets
wer compiled code which is in intermediate language, which is I_L.
Then, converts that or recompose that into machine code at runtime.
In.NET Framework version four,
they added a new component called DLR,
which is a Dynamic Language Runtime.
So DLR sits on top of CLR,
and gives dynamic language capabilities to C#.
Now, most often we are not going to work with that, it's just there.
I'm just telling we that this is how the magic happens.
Now, let's take a look at a few other things about dynamics.
I can define a dynamic, type here,
give it a name here,
and assign it to my name.
And then, the next line,
I can assign an integer to it.
And that's perfectly fine.
With static types, like object, int, string,
or whatever, this is not possible — we're going to get an exception.
But if I run this code,
the application runs successfully.
There are no exceptions.
Let's inspect this, I put a breakpoint here with F9.
Run the application in debug mode with F5.
Continue execution with F10.
Let's put a watch on the name variable.
Take a look here.
So name is a dynamic,
and it's runtime type is a string.
But if I continue execution with F10,
now its runtime type changes to integer.
And that's one of the key differences between dynamic types and static types.
With dynamic types, we can do whatever we want with them.
And I think that's what makes them powerful in terms of writing code faster and easier.
Now, let me show we another example here.
If I remove this line and instead try to apply a '++' operator to this name variable.
Let's see what happens. This time we got an exception.
Unhandled exception, its subtype, runtime,
binder exception which is a popular exception when working with dynamic types.
And the exception message says,
operator '++' cannot be applied to operand of type 'string'.
So, at runtime, let me cancel that.
So at runtime, the type of this name variable would be string.
And of course, we cannot do that with a string,
and that's the reason I told we — with dynamic types,
we need to write more unit tests to make sure application behaves properly at runtime.
Let's take a look at another example.
I'm defining a dynamic called "a",
set it to 10.
And "b", set to 10,
or let's say five.
This time, I'm going to define a variable with var.
Now, var is not dynamic,
var is basically a shorthand way of writing
code and letting the computer decide what type a given variable should be.
So if I say, var c equals string, empty string,
and I hover my mouse over var,
then var is a string.
It's a short way of writing code.
I could just write string here,
but var is a little bit shorter.
Now, the interesting thing here is if I define "c" as "a plus b",
because a and b are dynamic,
c will end up being dynamic.
Look, that's dynamic.
Let's put a breakpoint here.
Run the application in debug mode.
I'm going to do this watch here,
and put a, b, c here.
So, continue execution with F10.
So a is dynamic,
and this runtime type is integer — so is b,
and so is c. So when we use dynamic variables in an expression,
the expression will end up being dynamic as well.
One more thing we need to know about dynamics is conversions or casts.
Most often, with dynamics,
we get implicit conversion from and to the target type.
So let me show we an example here.
So I define an integer called "i" and set it to five.
Now I can define a dynamic called "d" and set it to "i".
In this case, I didn't have to specify a type cast or conversion.
At runtime, d will end up being an integer. Let's verify that.
So continue execution with F10.
They put d here, in the watch window.
So "d" is a dynamic and it's runtime type is integer.
Similarly, we can put dynamic on the right side of
the assignment operator without the need to do any explicit casting.
So if I define a long "l" here,
I can put d inside long.
At runtime, d will be an integer, and of course,
we can't put an integer in a long variable without explicit casting.
So the lesson is — when converting from dynamic to static types,
if the runtime type of the dynamic object is implicitly convertible to the target type,
we don't need to cast it.
So let's verify this.
So F10, F10, and I put a "l" here,
and "l" as we see it's long and its value is five.
And "d" is, of course, dynamic and its runtime type is integer.
Well, that's it for this video.
I hope we enjoyed it, and thank we for watching.
This course is part of a series of courses that help we master C#. Once we're proficient in C#,
then we can focus on specific areas such as web, mobile and game development depending
on what wer goals and interests are.
Here is the learning path that I recommend to we to get the most out of my courses:
Essentials
These courses are absolutely essential and we should take them in the following order. Do not
skip any of them!
Mobile Development
Once we master C#, if we'd like to learn how to build mobile apps with C#, we can take the
following course:
Xamarin Forms
Entity Framework 6
ASP.NET MVC 5
If we'd like to become a serious developer, I highly encourage we to take the following
courses too. These courses help we become a better developer and write better code and in
less time: