Transcripts
1. 0-1. Is This The Course For You and About The Instructor: So welcome everybody. Welcome to my C Sharp
video tutorial course. Here I have around
11 hours of footage teaching you everything
from the absolute basics. This assumes you have zero
programming knowledge at all. And at the end of this,
you will have the same, if not more, knowledge, about programming
and C Sharp than a typical university
graduate student. So if you want to learn C sharp as a hobby,
it's no problem. You're going to get that
out of this course. However, if you want
to get a job or potentially a career at
the back of this course, then again you're going to have no problem doing that either. And for those of you
that perhaps want a C Sharp refresher or a
generic programming refresher, then this course is also
good for that as well. So is this shop video
tutorial course good for you? Well, do you want to learn shop? Then the answer is yes. But perhaps a better
question is why should I choose this
course over any others? Well, the secret to
learning is, number one, the teacher, and it's how the teacher teaches
the information. And number two, the
learning process. Is the course engaging? Yes, it is. Is it boring? No, certainly not.
Is it confusing? No, because I explain
principles in not just one way, but perhaps two or
three different ways. So at the end of this,
you're going to get a full understanding of every technique that I
teach you in this course. And the pacing, is
it fast pacing? No, it is not fast
pacing at all. This course is designed
for absolute beginners. So the pacing is slow, at best. Who is this course for? This course is for
absolute beginners. It assumes you have zero
programming knowledge, zero software
development knowledge, and you want to get started
with C sharp programming. Maybe you want to do
some games in Unity. Maybe you want to develop
software applications, mobile apps, websites in C shop. All of that is achievable by watching this video
tutorial course. This course does assume you
know how to use a computer. You know generically,
you can move a mouse, maybe check your e mails, and download a file. But the point is, it doesn't assume any programming
knowledge at all. So the learning
experience, well, I enjoy psychology
in my free time, so I understand how
the human mind works, especially when learning
and retaining information. But perhaps a new and
daunting subject. So that brings me to the
next point, the pacing. What is the pacing
of the course like? Well, programming has a lot of big and complicated
technical words. But don't worry, I introduce technical words very slowly
throughout the course. Many teachers use complicated
words immediately, and it causes a lot
of confusion and it hampers the ability to
retain the topic at hand. I find this a very important step to prevent
your biggest enemy, which is information overload. So don't worry,
you're going to learn the complicated and
technical words, but not before the
topic at hand. I will introduce
it slowly so that the learning experience
is a very enjoyable one. So as the course progresses, I'll slowly start introducing
the correct industry terms and technical jargon when watching the videos
from this course. I appreciate you're
not there to ask questions immediately
and get direct feedback. So what I do, I explain topics
in various different ways, not just one way,
and that way you can fully understand
the subject at hand. I feel this method of
learning is far better than making videos where you don't
provide enough information. If not enough
information is provided, then you feel lost
and frustrated and there's no teacher
there to ask any questions. You will not experience
this with my course. And I guarantee that
because even after I've explained a complicated
subject, for example, in numerous different ways, then if you have any questions, you can feel free to leave
me a message or a comment. And I'll be more than
happy to address any questions or concerns you have at any moment
during this course. And lastly, if I teach you
a programming principle, I don't just teach
you the information. I actually explain
why they're useful, why you apply this
in everyday life, and why it's important in C sharp development to do
this particular principle. So that is where my course differs from a lot of
courses out there. You learn the how and the what, but also the why, which is very important. Engagement, one of the
biggest killers of learning new information is
engagement and motivation. The two kind go hand in hand. So what I do, I
use fun examples. Also, I use trending examples as well to keep
things interesting. I understand what it feels
like to lose motivation and lose engagement and get a bit bored when
learning a new topic. So I try to keep
things fresh and current so that you'll
never lose motivation. And you'll always stay engaged
with the topics at hand. So what will I get out
of learning this course? Why should I learn from you? What is the end result? What can I achieve? Well,
very good questions. I will teach you everything
you need to know about shop, but not only C shop
programming in general. The tools and techniques and principles to make
you a good developer, a good programmer,
especially in shop. And it's going to be similar, if not better, than a
university graduate student. How do I guarantee
these bold claims? Well, I've been to university, I went for four whole years. And I can guarantee
that the content of this course is exactly what
I learned in university. But not only that, but more. And I also teach you
the tools, techniques, and best practices that I've picked up working in
industry as well, so in a professional capacity. So whether you go to university
college or you don't go, you have an advantage because
you're not sitting in a classroom full of people
with a lot of distractions. This is a unique one
on one experience. So lastly, I'll
summarize by saying, it doesn't matter what
type of learner you are, whether you're a visual learner
or not a visual learner, you can watch this
course by sitting in a chair and eating a
pizza, for example. However, if you want to
be more interactive, then I provide the full project files along
with this course, all the source code that I use. So if you want to
follow along at your computer, you can do that. No problems at all. This course offers
multiple ways of learning for various different types of learners out there. So about me, who am
I, What is my name? Well, I'm Sean and it's
nice to meet you all. I'm a professional, self
employed software engineer. But not only that, but I teach software development
and programming. I work with many different
programming languages and also many different
architectures. But because I regularly
teach students, I haven't lost the ability to communicate
with new learners, especially on a beginner level. I graduated university
now back in 2007. I have over 20 years of professional experience
in software development. I was even working alongside my university studies
in the same field. I've been teaching
programming now since 2003. So a long time ago, I used it as a way to fund my university studies before
Youtube was even a thing. I'll show you my very
old website now where I made video tutorial
courses in Visual Basic, six C plus plus Java, Direct X, and various things. So you can see that now I've taught many
people programming. And they always come
back to me later, you know, ten years
later, 15 years later. And tell me all about
their success stories, the companies they're
working at now, and what projects they've
been involved in. So it's really wholesome
and interesting to hear these success stories
from my past students. And I love it when students come back to me
and tell me about their success stories and
how their life has changed. Learning, programming,
it's really interesting and it's the
best part about teaching. So I'm self employed now, but I've worked for many
businesses in the past. Small companies and
large ones too, perhaps you've heard of a few. I've worked for The Guardian, which is a newspaper company
based out of central London. I've worked for the British
Ministry of Defense, where we worked on
Cad software for modeling their surface
ships and submarines. I've worked for Pfizer, a pharmaceutical company, which I'm sure you've all
heard about these days. But when I was working there, not many people have
heard of that company. And I've worked for
various small agencies that perhaps I'm sure
you've never heard of. So I can share my
experiences from working in small teams and also
very large teams. And examples of both of
these different types of experiences I'll share
throughout this course as well. So if you are wondering where
my accent is from, Well, I was born in the UK and my programming ventures have taken me all around the world. I moved to America when I was 25 and got citizenship there. And now I'm living
in South America. But one thing that has
remained consistent, rather than my home
and my accent, for example, is that I've
always been teaching programming and I've always been doing software development. So enough about me. Let's
talk about C sharp now.
2. 0-2. What is C# in Game Design? and Why Learn C#?: So what is C Sharp? Well, C sharp is what's called an object oriented
programming language. And don't worry, we'll be
talking all about that later. It's created by Microsoft and it runs on what's called
the.net Framework. C Sharp has its roots
in the C family. So I don't know if you've
heard of C or C Plus Plus, but it's quite similar
to those languages, and this is where it
was developed from. It's very similar to popular languages like
C plus Plus and Java. And the first version of C Sharp was released
in the year 2002. Now, so it's over 20 years old. And the latest
version at time of filming is C Sharp version 11. So the C Sharp language slowly evolves pretty much like
everything else in life. So why should I learn C
Sharp? What is it used for? Well, you can create
mobile applications, desktop applications, web applications like
websites, video games, virtual reality games, for
example, machine learning, software, database applications,
and much, much more. It's one of the most popular programming languages
in the world. And this is why it's
really good to learn a language like C
Sharp because there will be more job
opportunities out there and more opportunities for you to apply your knowledge. It's easy to learn and
it's simple to use. It has huge community support. If you already know C
or C plus plus or Java, or maybe you want to
learn them in the future, then they're very similar. The principles I teach
you in this course, you can apply to C plus plus and Java if you wish to pick up a
new language in the future. One of the trending things
right now is to create video games in a software development package
called Unity. Unity supports C Sharp
behind the scenes. If you want to make your
video game do things, make your characters move, then you can use C sharp
to accomplish this. So right now, people are
learning C sharp more than ever, just so they can create
video games in Unity. So here is a lot of
reasons to learn C sharp and why you should learn C Sharp over perhaps
other languages. So hopefully, through
my explanation so far, I've convinced you to
begin your journey in learning C Sharp and becoming
perhaps a professional, or even a hobbyist, programmer. Now let's begin our
adventures in C Sharp and download the tools we
need in order to get started.
3. 0-3. Downloading and Installing Visual Studio (C# IDE): How do we start
coding in C Sharp? Well, the easiest way to get started is to use
what's called an IDE. This stands for Integrated
Development Environment. And the environment
we're going to be using is called Visual Studio. So we're not going
to be coding in Notepad or anything
scary like that. We're going to be
using beginner, user friendly tools which
are provided by Microsoft. And not only that,
they're free of charge. Let me show you how
to download and get started with Visual Studio. Let's start downloading
Visual Studio now. If we come over to Google and just type in Visual
Studio Community, and we can click the
first result right here. Now, the latest version
at the moment at time of filming is
Visual Studio 2022. But even if you have
an earlier version or a later version, a lot of the techniques we're
going to be covering in this course are going
to work. No problems. So we're going to click
this first link here. Here we can download
the IDE right here if you're using an
Apple Mac, for example. Then you can click
this button up here. And then Visual Studio comes
in three various flavors. We have the one for
Windows right here, the one for the Macos, and also a lightweight one
for Mac, Windows, and Linux. So depending on your
operating system, you should be pretty
much covered. But I'm running a
Windows machine and that doesn't really match. If you run Mac, you can still follow the tutorials,
no problem. So I'm going to click
this download link here, and then Visual Studio is
going to start downloading. It's only a 34 megabyte file, so it's very small, But everything
will be downloaded inside the set up file itself. Just before we install
Visual Studio, I want to mention one thing. Visual Studio is not just
tied to C Sharp development. You can do so much
in visual studio. Visual studio works with
HTML, CSS, Javascript. You can even create
mobile applications, Php, Python, Spot, Net. All these various things, tools, technologies, and
programming languages you can do in visual studio. So if you already know
a different language, or maybe you want to
try different languages in the future after
looking at C Sharp, then Visual Studio will support you through
those endeavors as well. So it's a very powerful
piece of software, and again, it's free. Let's open the Visual
Studio setup file, which we just downloaded and get with installing
Visual Studio. So let's click continue here. Now it's just preparing
the installer, it's downloading a
slightly bigger file. Now this is the window
that you're going to see once the set
up is initialized. So lots of different
things you can do here for the purposes
of this course. The only thing we're going to
be working with is C Sharp. The only thing we need is the.net Desktop
Environment right here. So you just click
this box right here, and then we can get
with installing these components. Anything else? Here is totally
optional, and up to you, we have various things for
developing websites in Aspet. We also have Azure Node, Python. Again, desktop and mobile stuff, stuff in C Plus Plus. And you can even install
Unity from inside the visual studio installer and various data
components as well. So there's lots to be
done, lots to install, and lots to learn in terms of programming and working
with visual studio. But for what we need is only
this simple box right here. If you speak another language or you're more familiar with
a different language, you can select it from here. It's no problem at all. So if we come over to here now, this is everything that's
going to be installed here. To be honest, I
don't think we need live share model
builders or blend. It's just going to
blow our installation. But I think this is a good set up to get started with
and it's going to give you everything
you need to follow this course and
even slightly more. So now what we're going to do is just click this install button. Here you have a
couple of options. You can download it all, then install, or you can
install while downloading. It doesn't really matter,
it just depends on your preference and perhaps
your Internet connection. So let's click the install
button and get started. The installation may
take a few minutes, but once you see this
screen right here, that means visual studio has
been successfully installed. You may also have icons on your desktop or in
your programs menu, depending what operating
system you're running. But essentially, once it
appears in this list, then you have Visual
Studio installed. What we can do,
we can just click this button now and
launch Visual Studio, and then get started with our software development
in C. Sharp.
4. 1-1. Hello World (Mr. Beast Logo): In this lesson, we're
going to create a very simple piece of software called a
console application, and it's going to
display the Mr. Beast logo to whoever opens
our piece of software. Let's get going now. Visual Studio has been
freshly installed. We're going to create our very first
software application. It's going to be
our very first one. It's going to be
beginner friendly, and we're going to take it
from the top. Let's get going. Once Visual Studio is open, we're going to click
File, New Project. Then we'll have a window
that looks similar to this. Now if you don't have
Visual Studio 2022, that's the version
I'm using right now. It may look slightly different. You may see settings
in different places. Things might be called
something slightly different. But the general kind of
principle still applies. Now our very first
software application, it's going to be a console app. And this is represented by
this project template here. What a console application is, it's kind of like
a black window. It just has text on it. And the reason I'm using that is because it's very
beginner friendly. There's no buttons, lists, images, or anything complicated. This is very beginner friendly and this is why I'm using
a console application. If you don't actually
see that in this list, you can search for
it here by typing in console app or
console application. And you can see all these
templates will load up here. We want this one because
we're writing in C Sharp. It actually will run on
Linux, Mac, Windows. We're going to use this one,
we're going to click next. We can call this whatever
we want. It's up to you. You can leave it like
that, or you can choose something
more descriptive. So we're going to call it
first program, the location. You can choose a
directory where you want to keep all
your project files. That is up to you.
So let's click next. Now this framework,
I'm going to talk of all about frameworks
in a later tutorial. I want to keep this
very simple, this list, it might have 4567,
all different numbers. We're just going to
leave it at seven. If your four is fine,
it's still going to work. If you see this checkbox
here that says, do not use top level statements. Make sure it's checked. This is very important. Let's click Create. And this
is what we see right here. Now Visual Studio is actually given all of this code for us, and the reason they
do that is to make it more user friendly
so we can get started. As a first time user, you probably have no
idea what this means. That doesn't really matter. All of these lines here I'll be covering in a later
tutorial and you will learn what they mean in time to keep this
beginner friendly. The only line right now anyway, you need to concern yourself
with is this one right here in this tutorial. We're going to put
all our code between this curly brace here and this one here, all
in the middle. And we can put more lines
in here if we want to. In this tutorial, we're only talking about this section here. Do not worry about any of this. Let's remove all
that complexity. Let's talk about this.
What does it do? It says console right
line, Hello world. In order to actually try
and run this program, I need to talk about what
is called a compiler. Now, Visual Studio, it has an inbuilt compiler because
we're writing C Sharp. It has a Sharp
compiler in there. What the C Sharp compiler does, it takes all our code here, that's everything in this
white window, compiles it. If we're using
Windows, for example, it's going to create an EX
file for us what an E file is. It's called a binary file, maybe you don't really need
to know that right now, but it's called a binary file. If we want to run
this program on say, a Mac, for example, then it's going to
create a binary file that a Mac would understand. If we want it to run an Android, like an Android phone, it will create a binary file that the Android
phone can understand. That's really what a compiler does in a very small, non
complicated nutshell. It takes all of our
code and compiles it into one binary file. In order to do that, in
order to run the compiler, you see this little
green play button up here where it says our project
name called First Program. When we click this button, this is where we say,
oh, hey, Visual Studio. Can you tell our
compiler to take all our code and make it into a file so we can
run the software? That is exactly what it does, so we're going to
click this right here. What happens is our
little black window appears and immediately
disappears. Two things here, all of
this stuff down here, you saw all that
text going crazy. That is the compiler. The compiler is saying,
okay, I've done this, this, this, can I spat out this EXE
file at the bottom of it? That's because I'm
using Windows. It's created an EXE file for me. Now the EXC file
has been created. The software is run. It tries to open
the EC file for us. That was that black window
that just appeared. But then it instantly
disappeared. It instantly disappeared because we're not actually
telling it to stay open. Visual Studio did a good job of putting in this
sample code for us, but it also keep the software open so we can actually see
what is going on. I'm going to type one more
line and that's going to keep the black
window open for us. So I'm going to type console because console is
the black window. So we want to say, oh, hey, console read line, right? So that is what I'm
putting there and that will keep the
console window open. Let's talk about this
line real quick. What this does, it
waits for user input. So for example, have
you seen a software, any piece of software that says, hey, what is your name? And then you type your name? So what happens is when
we run this line of code, the black window is
waiting for our input. And that just keeps
the window open. Let's just run
this software now. Now you can see the
window is open. It's actually stayed open,
It's not going away. That's just because it's
waiting for our user input. But it's kind of
like a little dirty, kind of hacky way of keeping. So we can see what is going on. This black window here is
our console application. It's our very first
piece of software. Pat yourselves on the
pack. It doesn't do much. The only thing it does
is say hello world. It's telling you it's alive. It's saying hello to the world. That's all it does right now. Very simple, but don't
sell yourself short, it's your very first
piece of software. We can either close this by hitting Enter or
crossing it off here. And that is it in our nutshell, our very first
software application. Now how do we expand on this? Well, let's talk about
one other thing first, that is case
sensitivity in C sharp. And a few little
caveats as well. You notice here where it says
red line and right line, it's actually case sensitive. What that means is if I change this upper case L
to a lower case L, you can see I have this red line underneath that's saying, oh, I can't actually find this in the system.
It doesn't exist. That's because a lower
case L and an upper case L in C sharp are two
very different things. Bear that in mind. It needs
to be case sensitive. The last thing is that all lines must end with a semi colon. If you forget the semi colon, then we're going to get
a similar thing happen. You see this little
red squiggle here. If we hover over
that with the mouse, it's saying semicolon expected. So it's actually telling
you what the problem is. If you ever have an
era where you have the red squiggly line and you
try and run the program, you're going to get
something like this. And you will get
very familiar with this dialogue in your
programming ventures, trust me. And then it'll tell you what
the problem is down here. You can double click it
and it alerts you to this. And that's just saying
the semicolon is missing. Now, I've talked very
briefly about what these do. Let's just talk
about this bit here. What we want to do is say, oh, hey, black window. Write the line to the window and we want to
write hello world. That is all it's doing. You fully worked
that out yourself. But now I've told you that we can actually expand on this. We can actually say, oh, hey, that's right,
Three hello worlds. We save that, click the button, and now we have three of those. Now you see where this
is going in our example. Right at the start I
said we're going to display the Mr. Beast logo. Now I have an ask
file for the Mr. Beast logo. Ski is just a text
representation of an image. I'll show you what
that means now. It's all going to make sense. So you can see
here, I have a Mr. Beast logo here in Notepad. And I've added the console
right lines before it, so we can see that here. I'm just going to
copy all of that. And I'm going to
paste it between these curly braces like I talked about earlier right there.
I'm going to save that. I'm going to press
the green button. I'm going to open this
window so we can see it. And I'm going to scroll up. That's our very first
piece of software. As soon as someone opens
your piece of software, they're going to see
the Mr. Beast logo. It's that simple how we can modify that message and
create a whole new picture. When we look into the code here, it's just multiple right
line statements that creates all these Ms here and a very nice character
design on the logo here. Before I end this lesson, I'm just going to show you
how this all ties together. It makes sense in your head. Remember when we created a brand new project and we
have this location field? Well, I'm just going to go
into this folder right now. Now I'm in that directory
on our computer. We can see Visual
Studios created a series of folders
and files for us. Inside here we have what's
called a solution file here, and it's created another folder. So we'll go in there. It's
created even more files. This one has our coding. But if we look inside
this bin folder here, and then inside this
debug folder right here, inside this one,
you can see there's a few files right here
in the middle here. This is our binary file, and because I'm using Windows, it's created an EXE file, Fas. If we double click this, we can even send it to
a friend, for example. They can double click it. When you maximize it,
you can see the Mr. Beast logo. You can see this
is how it all ties together. Visual Studio tells
the compiler, oh hey, take all the code,
Create a EXE file, Fas, and put it in this
folder right here. All of the other files I'll
talk about at a later date. But for the purpose
of simplicity, it creates our EXE file fas, and that is our very
first piece of software.
5. 1-2. Variables: Now we're going to talk about is I'm going to introduce
a very simple variable. I'm going to show
you how it works, what variables are
and how they can benefit and things
like that, variables. Let's talk about what they are. For a start, we have a
sample application here. It just says, hello
world to a black window. And that's all it does, as
you can see right there. Now I'm going to
introduce what's called a variable and I'm going to talk about
how they can help us. Let's just introduce a variable. I can talk about
this in a second. I'm going to call it test. We're going to give it
a value of Hello world. I'm just going to put
the variable name here. So let's talk about this
and what this does. So what I'm doing here, I'm initializing what's
called a variable. Now this is the variable. It's called test, so this is
the name of our variable. Now this variable can be
called anything you want. It could be called ham sandwich. It really doesn't matter. But the point is you
need to give it a name where it makes sense to
you, you can refer to it. Because when you have
a software application that has thousands of variables, you're going to
get very confused if you call them all
different types of sandwiches or random names like test or
something like that. So it needs to
make sense to you. So I'm just going to
call it hello World. So that's the name
of our variable, this is the value
of our variable. So this is what we're putting
inside our variable here. Now this part here is
what's called a type. Now this is a string variable. What a string variable is, it's a container for
words, sentences. You can put a whole book
in here if you would like. It's all alphanumeric letters and numbers, but as a string, it's not numbers by themselves, it's not a decimal value, it's not a date or a time or anything
complicated like that. That's what a string is. That's what's called
a variable type. That's the variable type
that's saying, hey, computer, we want to start a new variable
and put it into memory. The name of our
variable is this. The equal sign is how
we initialize it, like give it a value. When you're working
with strings, we always put the value
in double quotes. Like inside the double quotes is the value for our variable. We always end every
line with a semi colon. Now our variable is called Hello World. Let's
run the program. You can see it outputs
Hello World to the window. It does exactly the
same as it did before. That's to be expected because we haven't
changed anything. We've just declared
and initialized a variable and we're outputting it to the
black window like before. Exactly the same thing
we're doing here. One thing real quick,
with variable names, what I always do is use title case always with a
lower character at the start. Now this is up to you, but generally this is how
people tend to use variables. Maybe when you work in a
company in the future, if that's what you want to do, other people will
do a similar thing. It's good to introduce
good practices. Now, that's the only
reason I do that. Then every next
word, hello world. This will have upper case. If we have another word here, then that one will
start with upper case. That's just what's called
standards, it's optional. Let's talk about what
declaration is and what initialization is to
cover those two terms. I'm going to expand on
our little example here. I'm now going to how
are you like that? And then I'm going to re output the variable to the screen. Then I'm going to
run the application. So you can see what is going on. You can see here in the
window it says, hello world. How are you? Have a
look at how that works? You can see here, we've
defined our variable, we've given it a type. Now, we only give the
variable a type once. We're saying, oh, hey, computer, this is our variable
I want to use. This is our new variable, by the way, it's a
string variable. Now, we've done that one time. We no longer need to tell
the computer it's a string, the computer already knows
and it remembers this. Now, every time we
modify our variable, give it a new value, we're just going to overwrite
what is already in there. When this line comes along, this part will be replaced
with how are you? And then we're putting
it back out here. We don't have to declare and initialize our
variable on one line. Let's take a look at
this example here. I could equally do this. The same thing will happen. What I'm doing here, I'm
declaring our variable, declaring means hey, computer, I want to create a new variable. I know it's going
to be a string, but I don't know what the
value is going to be yet. Maybe I'll decide at a later
time. At a later time. Okay, I've decided what
the value will be. It's going to be hello World. Then I want to output
it to the screen. And then I'm re initializing it here and outputting
it to the screen. This is declaration or
declaring a variable. This is initialization
or assignment. There's some words you're
going to hear in the future if you continue to
program with C Sharp. You can see we're doing
this on two lines and the output is exactly
the same as before, which is to be expected. One last thing, If we declare
a variable here and we attempt to output it without initializing
it or assigning it, then it's going to
throw an error. We can see this
red squigly line. When we hover our mouse
over the red line, we have a little bit of a clue
as to what the problem is. And it's just saying use of unassigned variable,
hello world. It's telling us what
the problem is. Anytime we have an error, we can't run the program because we always need to
fix these errors. That is a very basic view on how variables work in C sharp.
6. 1-3. Data Types: Okay, let's talk about
data types, what they are, how they can help us, why we can use them, and everything in between. So I have a sample
application here. It doesn't really do much. We declare and initialize
two string variables here, and we output them
to our black window. When I run the application here, it just says Sponge
Bob square pants. I thought of an example on how to explain data
types a lot easier. I came up with an example. Have you ever played
Top Trumps or Pokemon cards or gear
or something like that, where you have the
name of the character, maybe some attributes like age, weight, height, rarity,
or things like that. I think that would represent
data types quite well. And help me explain them so you understand
them a lot easier. Imagine a card that has a name
and it might have an age. For example, this is the
age of the character. Now Sponge Bob is one
of those characters that transcends all age. I'm going to put 21. This is a string type variable, This is a data type. Another data type we can use
is what's called an integer. Now what an integer
is, it's a number. We can actually hover over it and visual studio actually gives us more
information about this. It represents a 32
bit signed integer 32 bit just means the size. How much information
you can put in here. I think it's anywhere
from negative 2 billion to positive 2 billion. I think using age
fits this quite well, it's only going to be 23 digits. When we use integer
type variables, we don't need these double
quotes like on strings. We just need a
number right here. Another one, maybe the weight, and that will be in pounds. Maybe this sponge is
around 120 pounds, something like that.
Another one height. Now height, we're going to
put it in feet and inches. I'm going to put it
in feet and inches so I can show you a new data type. This is called a double. Now what a double is, it represents decimal numbers. Let's put height in here. Let's say our sponge
is three feet, 4 ", for example.
Something like that. So that's the height
of our sponge. If we have a over double here, it represents a double
precision floating point. Very complicated, isn't it? And this is why people
learn from tutorials, a double represents a decimal. This is anything with a
decimal point. Now, decimals. Let's talk about
decimals real quick. In C sharp, we can represent a decimal number in
one of three ways. Another one is called a float. Let's put numbers after this. When you use a variable, they all need to
have unique names. Let's do decimal. That's another way how
we can decimal numbers. These are the three ways we can represent decimals in C sharp. The main difference
is the precision. Now float is, I believe, 32 bit. It's only seven digits. You can give it more
than seven digits, but it will cut it off. Truncate it at seven. You lose everything
after seven digits, which is all this accuracy here. Now a 64 bit. Slightly more, I believe. 15 digits, 15 to 16 digits.
So it's more accurate. So we can put up to 15 in here. By default, a double is used when you use decimal
numbers in C sharp. When I say default, I'll
explain that in a second. The last one is decimal. This one is, I
think it's 128 bit, lots and lots of digits. I think 28 digits, quite long. We use decimals when we talk about things to do with money. Maybe if you write an
application to handle taxes as a government agency, for example, we want to make sure everyone pays their taxes to really far out
their decimal point. When you deal with money, it needs to be really, really accurate and that's
where we would use a decimal. You can see here
when I initialize this float data type
variable height one, I put a little F
at the end here. This tell C sharp. Hey, I want to initialize
a float value. This is because it uses
double as default. You can see when I
initialize a double, I don't need to put
a letter at the end. Anytime I put a
decimal value here, C sharp will assume
it's a double. If I want to initialize
a float here, I have to say, oh, by the way, this is a float data type. Because if I don't do that, you can see there's a red line. I hover over it. It says, literal type double cannot be implicitly
complicated, isn't it? It basically says, use an suffix to create a
literal of this type. It's basically saying, hey, you have a float data type, put an F at the end
and then we're happy. Same with decimal, I
don't know whither you don't use a D or something
more descriptive, it's probably used
by something else. This one wants an M. And
similarly, if we don't put an M, it's telling you to
put an M. This is why IDEs is called IDE, like visual studio, really good. It's actually telling you what you're missing and
what you need to do. If you use something
like Notepad, it's not going to tell you this. It helps you program
a lot faster. So these are the three
ways we can represent decimal numbers and we're just going to use a
double for the height. The height of our
sponge is three point, I don't know, three feet, 4 ", something like that. I think that would be
good. Now, the next one I want to introduce is a
Bolen represented by bool. This what could the booling be? Whether our trading
card is first addition? So I'm going to put
is first addition. I'm going to say true. Spongebob is a very
rare trading card and it's first addition,
so it's going to be true. Now booling data types can have the value true or they
can have the value false. Only one of those
two values true. If it's yes or false. No. That's how we use
boolings in C sharp. It's true or false.
Only two valuables. If you want a variable that might have three or four values, then don't use a booling. Booling are for only two values. The last one I'm going
to talk about now, there's loads of data
types in C Sharp, We can do dates, times, various complicated things like lists and things like that. But to be honest with
strings, integers, decimal values like the double
boolings and characters, here we can pretty
much write anything, lots and lots of software
with only these data types. Perhaps we will cover
more in the future. The last one I'm going
to talk about is characters represented
by Shah, right here. For this, I'm going
to call it grade. The grade of our card,
is it excellent? So that might be a or is
it bad? That could be an. Then an average card might be
like when you take an exam. So our grade might be
something like that. And this is a very good card. It's first edition mint
quality give it a grade of A. When you initialize
character variables, we use single quotes, not double quotes here. Visual studio does
a good job here. If you forget the quotes, it will probably
tell you you need them or give you a cryptic
error like this one. Yeah, so now we've declared and initialized
all our various variables with all their different types. Now I just want to output
them to the screen. You can see they have the green
line under each one right now when I use age down here. Watch that green line
disappear under age, and that's because
we're now using it now. I'm going to put one for every different variable here through the power of editing. We can see here now
we're outputting all of these to the screen if
we run this application. Now we can see all our various values for
all our different variables. We see the first
name, the last name, the age, the weight, the height. True because it's
first edition and also it's a very
good trading card.
7. 1-4. C# - A Strongly Statically Typed Language: I want to talk about two
things now to do with C Sharp, now that we understand
what data types are. Now C Sharp is what's called a strongly typed language and also a statically
typed language. Let's talk about what
those two terms are. A strongly typed language, that means once we've
defined a variable called first name and we've given
it the data type string, it has to be a string throughout its whole lifetime
of the application. We cannot, for example, take first name and then give it an integer value because
it won't like that. That's because it's a
strongly typed language. However, if you use a
language like Python, for example, you can do this, it's no problem at all. That's because it's not a
strongly typed language. In this case, that's what a
strongly typed language is. Once you've defined a string, you've given it a unique name. You cannot then stuff a
different data type into here. You can't say, oh, now I want to say it's true, For example, it's
not going to work. It's going to tell
you that's what strongly typed language
such as C Sharp, the last one is what's called a statically typed language. If we make an error to do
with one of these data types, for example, we have first name. Therefore it expects a
string in double quotes, like here, if we give it an integer, it's
going to complain. It's going to give a red
line underneath when. Anytime we have a
red line underneath, something like this error here, we can't compile
the application. It's not going to letters, it's not going to letters. For example, if
you're using Windows, compile your code into an EXC file and give it to a friend to run. It's
not going to work. That's because these errors
are caught at compile time. And that's what a statically
typed language is. If we make an error
such as this, we're not going
to discover it at a later date when a user
is using the software. That's quite a good
advantage of C Sharp and also languages like C
plus plus, very similar. Once we have a data type string, it needs a string value. These errors will be
caught at compile time. And that's when we press this green little Play button here. That's what a strongly
typed language is. And also a statically
typed language, C Sharp is both of these.
8. 1-5. Working with Strings and Substrings: Okay, let's look at
how we can work with some string type
variables in C sharp. Here we have a
sample application. We just have first
name, last name, and we're outputting both of those two our console window. Now, how can we actually
join two strings together? I have one variable first name, one variable last name. Right now it puts them separately
on two different lines. But how do I join
these together? What we can do here, what's called concatenating
two strings, and that's just a fancy way
of saying join them together. Concatenation, it could
be like concat for short. These are words you're
going to hear perhaps in the future if you continue
your C sharp journey. Let's look at joining these
two strings together. What I'm going to
do, I'm going to use what's called a operator. So you can see this plus here. And what that does,
it just takes this, this string and joins them together. Very simple, isn't it? So now we run the application. We can see we have sponge Bob, square pants on one line. But you can see there's no
white space in between here. So let's look at adding that. What we can do here is add another string and
use the plus symbol. Again, what we're doing here, we're taking the first
variable, first name. We're concatenating it, joining
it to this empty y space, which is also a string. And then joining it
to the last name, which is a variable here. Now, this isn't a variable, we don't need variables in here. We could easily do this, and it's exactly the same. That way we're not even
using that variable, but the output will
be exactly the same. That's how we can join
two strings together. Just so you fully understand, we can even create
a variable here and we can do first name
plus last name. Then we can put full name in here and we're going to have
exactly the same result. Let's not forget our
white space here. It looks presentable and we're going to run
the application. You can see here we have
exactly the same result. We're just using a variable
here called full name. And that's just adding
these together, concatinating them
together, white space. That's how we can join
two strings together, Very simply, substrings. What is a substring? Now, a substring is just one of many different things you can
do with strings in C sharp. Here's an example. Here we
have a variable called name. It has sponge Bob square
pound sets the value. And we're out putting it to
the screen now, for example, say I want to extract a
certain part of this string. I want to extract the
word sponge from it. I don't want the
rest of this stuff, I only want this
part right here. Now what we can do, we
can use something called a substring method to extract
a portion of our string. And that's what a substring is. It's a part of a string. I could take this,
I could take this. I could take anything I want. I could even take one
letter if I wanted. Let's look at how we can
actually use a substring. What I'm going to do, I want to extract sponge, the variable. We can call it what we want, let's call it sponge. Why not? We want to initialize sponge
so we use our equal sign. When we work with a variable, what we can do is put the
name of the variable here, which is name, in
this case when we use a period or a dart, whatever
you want to call it. Afterwards we have all these different
things we can do with it. Some of the common
ones are always at the top with this black
star next to them. One of them is substring. We can do lots of
things we can replace. We can lower the characters. We can split it, lots of
different things we can do. Substring is what
we want to use. We can double click this when
we open parentheses here, we have a few options
we can do with it. Now, I'm going to talk
about this stuff a lot later when I
talk about methods. But for the most part, I'm just going to put two things in here. And that is what I
want to do here. Now, in C sharp, everything starts at zero. Index is at zero. This string here,
this character here, that is position zero. The P is position 123. Everything starts at zero. Remember that moving forward is character position zero of our string sponge
Bob square pants. So the first value here is zero because we want to
start at position zero. Then the next value is how many letters you
want to extract from the string sponge 12345.
It's actually six. Now we want to extract
the first six characters sponge right here. These are the values
we put in here. Now if this is confusing to you, let's go back to where we talked about console right line. We had console right line and we opened the parentheses in here. We want to put our variable
onto the black window. Now substring, in this example, we want to give it two values. And when we give it two values, we separate them with a
comma like so we want the first character
and we want to count six characters forward which
we should extract sponge. Now we want to put sponge on our console window so we can
actually see the result. Let's compile our application. We can see with output
sponge right here. That is very simplistically
how the substring works. If we want to extract, say, Bob for example, then we start a position six and count three
characters forward. Then we can see
we've extracted Bob, That is how a substring works. One other thing we can do is
what's called a replacement. We have sponge Bob
square pants here. Say we want to replace sponge
Bob with something else, say Patrick or
something like that. Let's create a new variable. We'll call it Pat for Patrick. It doesn't matter
what we call it. We're working with our namestring
here. We'll leave this. When we press the dot again, we get all these things we can do with it and we're going to double click, replace
with, replace. We can replace anything
with anything else. What I want to do, I want
to replace sponge Bob. I want to give it the
new value, Patrick. Always end with a semi colon. What that is going to
do is take the name, everything inside the name,
it's taking all of this, we want to replace
every occurrence with Spongebob type that we want
to replace it with Patrick. Then the result of that
operation is stored in Pat. Then we can put Pat here. If we run the application, we can see now it says
Patrick square pants. That's because we're replacing every occurrence of
Sponge Bob with Patrick. And when I say every occurrence, let's try this, run
the application. It's replaced every occurrence of Sponge Bob with Patrick. That is how replacement
works in C Sharp. And again, you
don't have to store the result of this calculation
into a whole new variable. We can shortcut that, just put it there, and that
will equally work just fine. You can see Patrick
square pounds Patrick. Patrick Patrick. You can see that is how replacement works when dealing with strings. Another thing we can do with strings is work out the
length of the string. That one is very simple. Here I have a variable
called example. This is everything inside
that variable to work with. Example, I put a little
dart afterwards and I type length to
make this quicker. You can double click
this or you can press the tab key
on the keyboard. That might be a lot quicker for you to enter these values in the future when I
compile the application. Now we can see that this sentence here is
44 characters long. That's quite useful
when you use substrings to extract certain
things from a substring. Let's talk about another
method called index of. Now what index of does is if you specify a word
like sponge Bob, it'll actually tell you the index of where
this is in the string. Rather than counting
1-234-567-8910, character position
22, for example, we don't have to count, we can actually use a method
called index of. If I put index, then I want to put in, for example, sponge Bob. That will be in double quotes, because sponge Bob is a string, we want to store
the result of this. Now if we hover over index of, you can see over here
next to this pink cube, it says t. That means
the result of this will be an integer s
define a new integer. I'll just call it index. Then I'm going to output
the index to the window. Let's run this real quick. You can see apparently
Sponge Bob is a character position 22 here. That's 22 characters in index of is another method which is quite useful to get the index of
whatever word you would like. You could put in, for example,
just something like that. If we run that, it gets the first occurrence of
which is this one here, 012, that's the
first occurrence. Again, it has lots of
different things you can do with index of,
but that's an example.
9. 1-6. Working with Numbers: Okay, let's look
at some examples of working with
numbers in C sharp. We're going to look at
multiplication, addition, subtraction, division,
all that good stuff. So let's get going. Let's have a look at
an addition example. So how we add numbers in sharp. We have a sample
application here. We're just defining a variable, setting it to zero, and
outputting it to the screen. So not really much
is going on here. We're going to use our variable. I'm just going to
do five plus four, which we know equals nine. I'm just going to
run the program and we get nine is
the output there. Addition is very simple, you can keep going with this, et cetera. Very easy. Same again with subtraction, we can pretty much
do the same thing. Five minus six is negative one. You can see subtraction
also very easy. Again, you can do
this, mix them both. It doesn't really matter. It will work this out
for you. Multiplication. Let's do three multiplied by four to multiply
numbers in C sharp. Use this asterix here, the little star, and we
should get 12 as a result. There again, we can combine multiplication with
addition and subtraction, just like you do in
mathematics, for example. Now this is where there's a couple of
gotchas With division, the divide sign is a forward, let's do an easy 13/3 Let's
run the application is one. Because there's one, there's
13.3 The result is one. That's how we divide
numbers however. Okay? Gotcha. Number
one is divide by zero. We can't actually
divide by zero. You can actually see now. Anyway, back in the
day a few years ago, if you did three by zero, you could run the application
and you would get an error. Because it's not a realistic calculation,
it can't work it out. Now we have a red
line underneath, and when we hover over that, it says division
by constant zero. It won't actually let
us run our program, but because the variable
result is zero, let's just feed that into
there and run the program. And again, it errors
just like it should. The first error we caught at compile time when we try
and run the application, because we're using zero here, it's telling us we couldn't
run the application. But when I gave it a
variable which is result, which also equals zero, we can trick it in order
to run the program, but we still get that error attempted to divide by
zero, which we cannot do. So that's something
you should always bear in mind when working
with division. You should never divide by zero. When we talk about if
statements in the future, I'll show you how
you can protect your program to avoid
dividing by zero and the other gotcha
with regards to division is using
decimal numbers. Let's look at a decimal
number example. We're going to use a
double data type here, and we're just going to
initialize it to zero. Now let's just do an example. Let's do 3.45 0.6 which
should work fine. You can see here,
here's the result which is in decimal format. However, if we do say 200/3 this is not a
whole integer number, it will have a
decimal place on it. However, when we run
the application, you can see it's actually
doing some rounding here. It's, I believe, down to the nearest integer,
which is 66. However, if we add 0.0 onto the end of these
and run the application, you can see this is
the true answer here, 66.666 reoccurring. Then it's rounding to seven. This is something you should pay attention to when working
with decimal numbers. C sharp will make an assumption because if you have
two numbers here, this 200 is an integer, three is an integer. Neither one of
these of decimals, it's only the result
which is a decimal. What C sharp is
doing it is saying, oh, hey, there's
an integer here. Oh, hey there's an integer here. I'm going to give you the
result as an integer. That's a little bit annoying. What you have to do is change at least one of these
to a decimal number. When you do that, you can see we get the true result here. That's just something you
should really bear in mind when working with the
division of decimal numbers. The next operator I'm going to show you is the
modulus operator. Let's just put this
back as an integer. Now, what the modulus
operator does, it gives you the remainder
of a calculation. Let me do an example real quick. The modulus is represented
by a percentage mark. Here, what this does, it says, how many times
does three go into six? Well, three goes into six twice and then
there's no remainder. The result of this will be zero because it's the
remainder of this. Again, if I do 22
goes into 63 times, perfectly again,
there's no remainder. However, if I put four here, four goes into six once. However, there's a
remainder of two, so this will be the result two. What modulus does, it gives you the remainder of a calculation. After dividing this
one into this, 14 goes into six once
with a remainder of two. If I run the
application, we get two, just like the very
first example, three goes into six twice
and there's no remainder, the result should be zero. Modulus is quite useful
when we want to know if a number goes exactly
into another number. If the result is zero, we know it's perfectly
divisible by that number. That's what modulus is, or modulo whatever
you want to call it. And it's represented by a single percentage,
just like that. Now I want to talk
about the order of operations when working
with multiplication, addition, subtraction,
all that good stuff. Let me show you an example. I have result, which is our variable five multiplied by four -2/7 I want to add on the result
of five plus one. Let's have a look
at this example. If you've done a lot of
mathematics in the past, then maybe you can skip
over this section. It might be quite
obvious to you, but C sharp works
pretty much exactly the same as mathematics
in the real world. If you've ever seen these things on Facebook or Instagram, and they say, oh, what
is the answer of this? And people are giving all
the wrong answers because they don't understand
the order of operations. Here we have this thing in mathematics called
bid mass or Bodmass. Let me show you that now. Bid mass, some people
call it Bodmass. It doesn't really matter.
The only difference is the I here and the o here. But they mean the same thing. So the first thing is brackets. If we have a
calculation like this, anything inside the
brackets happens first. Five plus one. That happens
first, which is six. And then we can remove that and that gets replaced by six. The next thing that
happens is the I or the o that's to the power of, or the square root of. We don't have any of that stuff in here, so we can skip that. The next thing is division. The division happens next, and that's 2/7 Now, I'm not sure what 2/7 is, it's a decimal number, but that will happen next. This calculation here. The next thing that
happens is multiplication. This right here,
this will get worked out next five multiplied
by four, which is 20. Then any additions after that, then the result of that will
get added to six followed by subtraction to
the very last thing that happens is this one here. That's the order in which
this is calculated. It doesn't happen
from left to right. Five times four takeaway two. It always happens
in the order of the symbols, just
like mathematics. For example, if we
run the program, well, it can all get worked out. For us, the result is 26. That is the order of operations. Something just to bear in mind when working with
this in C sharp. The last thing I'm going to talk about to do with
working with numbers, is two to the power of
two, which is four. If you're not very
familiar with mathematics, the power of just means how many times it's
multiplied by itself. Two to the power of
two is the same thing as saying two multiplied
by 22 to the power of three basically means two times 22 multiplied by two
multiplied by two. Again, that's what the power of. The reason I'm
showing you the power of is because the
power of doesn't have a symbol like
multiplication or subtraction, we have to utilize what's
called the math namespace. Now let's look at that.
Now if I say result, which is the variable
we've defined here, then I say math MAT H with a capital M. When I press
the period symbol here, there's lots of different
things we can do. All these are built into
our C sharp library here, and we can use any of these. Look, the sign, cars, tan, truncate, logarithm,
all this fancy stuff. But what I'm just
going to use is power, which is represented by POW. If we open brackets here, it's asking for our
first number down here, it says a double precision
floating point number to be raised to a power. Let's say we want to look
at two to the power of two. It's asking for a double, which is a decimal. I'm going to put 2.0 because it wants it
in decimal format. I want to raise it to
the power of two again, end it with a semi colon. Two to the power of
two is saying two, multiply by two. The
answer should be four. You can see here
the answer is four. If we want to do two to the power of three,
it should be eight. You can see where this is going, 163264128. There you go. That is how to do the power of, but not only the power of. You can actually
utilize a lot of things in this math class here, all different things here. But that is an example of
how to use the power of, and working with
numbers in shop.
10. 1-7. Getting User Input: Let's take a look at
interacting with our software. For the most part, when
we run our application, so far we just can see
results on the screen. But now I want you to
interact with your software. You can give it
some information. For example, let's take a look at how to do this
with a console application. Right now we have a
sample application, It's just printing what is
your name to the screen. When I run that, it's just
saying what is your name? I want to be able to type my name in here, for
example, Robert. And then when I hit Enter, I want it to say hi Robert, for example.
Something like that. We can utilize the read
line line right here. So far, we've only
used this line just to halt the application, so our window
doesn't close on us. Because remember, without this, the window just
instantly disappears. However, it does
have a function, what read line does. It actually captures
some input from us. What happens if we
hover over this? It actually tells you it
reads the next line of characters from the
standard input stream. Quite complicated isn't
What this basically does is captures our input when we hit the Enter key
on the keyboard. The result of that we
can store into a string. If we harver over this,
you can see string here. This is what comes back to us. We can define a new variable. We'll call it result. We
could call it user input. We can call it whatever
we would like. What we're doing
now, we're getting the result of this operation
which is read line that grabs anything we
type in there after we hit enter and it stores
it in this variable here. Then what I want to do is say hello to whatever
name you put in here. Remember how to
concateinate strings. We have our first
string here, hello. Strings are enclosed
by double quotes. Then we want to
join a string with the result of this operation, which is also a string. We're
going to do that there. We want to sound
really enthusiastic. We're going to do an
exclamation mark as well. We're joining three
strings together. Hello, the exclamation
mark, and the result, which is a string variable from the result of
the user input. Let's run this application. Now it's saying
what is your name? I'm going to put Robert. When I hit Enter,
we have nothing that is because we
haven't told it to keep the console window open. Let's put that back
down there again. Hit the play button,
type in our name, Hit, and now it's
saying hello Robert. It's quite easy, isn't it? And that's how to capture user input in a
console application.
11. 1-8. EXERCISE - The Number Multiplier Game: Okay, let's look at
a quick example now. A little practical
application to test your knowledge of working
with numbers in C Sharp. I'm also going to test some of the knowledge
you've learned so far. And I'm going to introduce the concept of
converting data types, converting a string
to an integer. Let's take a look at this now. So what we're going
to do, we're going to build a sample calculator, but our calculator is only going to multiply two
numbers together. It's not a very fancy
calculator. Let's start here. We're going to say welcome
to our number plier. We want to tell the
user what this is. We're going to say, oh, hey, welcome to our
number multiplier. Then we're going to ask
for their first number. This is the first
number, they're going to multiply to another number. What is your first number? We're asking the user what
their first number is. To grab user input, we use console read line. Then the result of this we
need to store in a variable, we'll call that first number. Now first number will hold
the user's first number. Now immediately you see this red line underneath
console read line. If we hover our mouse over
that we can see here cannot implicitly convert
type string to int. What it's saying is, okay, look read line gives you a string because we're
asking for the user's input. And they could put a sentence, they could put lots of letters. We don't know what the user
is going to put in here, basically, but we actually
want an integer from this. The user could type hello and we're trying to put
hello into an integer, so there's going to
be a problem there. What we want to do is
use the convert library. What that is, if you type
convert to a capital C, press period there, do we get lots of options
we can do here. What convert does?
It gives us a lot of different methods of
converting data types. What we want to do is convert a string because that's
the user's input. We want the result
as an integer, which will be our first number. When I press here, what I want is two int int 32. Perhaps I haven't
explained this yet, but a standard INT is
also considered int 32. It's a 32 bit integer. You can have a longer
integer which supports more digits or even
a smaller integer. Int 32 is a standard
integer in C Sharp. When I open parentheses on this, it's asking for a string value. This is the string
it's going to convert to an integer and
our string value, well that's the result
of the user input. That's console red line. We'll put that
there. We'll close our brackets and we'll
put a Sami colon. Now you can see the
red line has gone. Similarly, you could just store the result of this
in a new variable, a string variable,
and put that in here. It doesn't really matter, but we're doing it all on one line. Now what we want
to do next is grab the second number from the
user, the second number. That will be a new variable
called second number. We want to ask the user what
their second number is. Now we have the
user's first number in this integer variable here, and the user's
second number here. Now we want the result of that, that will be the result of
the calculation first number, remember multiplication is the asterix second
number semicolon. Then we want to tell the user what the result
is. Let's do that. We're going to say
the result is, then we're going to concatenate the strings together,
which is result. Then we want this so the
window doesn't close. Let's run the application here. Look, welcome to our
number multiplier. What is your first number? Why not number four? What
is your second number? How about number five?
And that should equal 20. It says the result is 20. Pretty cool, isn't it? Again, we can use different
numbers in there, but that is a very
simplistic view on how we can get user input
using console read line, how we can convert data types. So we're converting a string
which is the user's input, an integer which is
our variable here. Then when we multiply
our integers together, we get the result and we're just telling
the user the result. That is a very simplistic way of working with
numbers in C. Sharp.
12. 2-1. Methods: Now I want to talk
about methods in Sharp. We've actually used a
lot of methods so far. For example, right
line is a method, read line is a method to the power in the math
helper was a method. Now we're going to
create our own method. When creating
methods in C Sharp, they all have a purpose. If you have a job
which is usually done more than once or
a complicated job, you can put it in
a separate method. When I say method, here is
an example of a method here. This is the main method. Everything within this method here is within
these curly braces. Here, the main method is a special method when our software is
executed by default. The.net Framework, which is everything C Sharp
is built around, this looks for a special
method called main, and it has to have this name. And all method names are unique, so they can't have the same
name, just like variables. Once it's found the main method, it runs all the code within
these two curley braces. Here, the only code we have
are two lines right here. When we run the application, we can see Hello World. And the next line keeps
this window open for us. Now let's look at creating a brand new method where
it says static void. I will cover that in
a later tutorial. For now, let's keep
it very simple. After we write static void. In this case, we want to
give the method a name. Now remember I said methods must have a purpose to keep
things organized. Generally, they should
have a purpose. Our new method, what
I want it to do, its purpose, its job is to
say hello world to the user. That is the only thing
it's going to do. Now I know it's function, what it's aiming to do. I can call my method with a name that makes
sense to words. I'm going to call
it, say hello world. That's going to be
our method name. Now the next section are
what's called parameters. I'm going to talk
about those later. I'm going to keep
it simple for now. Do an open parenthesis
and a closed parenthesis. Next, open curbrace
and close curbrace. Just like that, you can
see it can mimic this. All our code for our
method will live here in this highlighted section
between this one and this one. All our functionality for
this method lives here. We want to say hello
world to the user. Well, we know how to do that, We've covered it before. That is this line
of code right here. Our method say hello world. Its job is to say hello world. So that's going to print this
to the black window easy. Right now when we
run our software, well, it's not actually
going to do anything. Why is that? That's because the main method is
run by default. So this section here, and this is the only
thing which is going to get run from our main method. We know nothing of this. What we need to do
here is say, oh, hey, can you run our method in order to run our method?
We just do that. When we launch the application, the main method is run. It goes down, this
line is executed. When this line is executed, the code goes into here. This line is run. The method
has finished its job. It goes back out to here, and then finishes off
with this section here. When you have a
method, it goes out, then back in again,
and carries on. If we run the application, now we can see Hello world. That's because we're
now calling our method. Just to recap if I
went too fast or it's complicated
without this line, our method will
never get executed. When we run our software, we can create lots of them. 3,000 5,000 1,000 Again, they all must have
a unique name. But when we run the software, none of this will get executed. And that's because we're
not actually telling the computer to actually
run them to run a method. Again, we do this again if
we want to run this method, very similar, et cetera. This is how to run the method, this is how to
define the method. And that is a very simplistic
view on how we can set up a very simple
method in C sharp.
13. 2-2. Method Parameters: Now I want to talk about
method parameters. A parameter is just
a fancy way of giving a method some
information. Here you go. Here's some information.
Work with it. We're going to use an example. Here's an example. We're just saying hello world
to the user. Very simple. But what if we want this
method to say hello John, hello Harry, or hello Roberto? These names are something
the user can provide to us. Here's an example. We're going to ask the user a question. We're going to say,
what is your name? What your name. And then we want to
get the user's input which is console dot read line. That's how we get
the user's input. And we store this into a string. I'm just going to call it name, asking for the user's name. The user types some
information and we're stuffing it into
a variable called name. Now, our method here, I want to say hello, and then I want it to say
the result of this variable, which is going to
be the user's name. We don't know what that is. The user can type
anything they want. Now, the job of this
method is changed. I don't want it to
say hello world. I want it to say
hello to the user. Now I'm going to say hello user. Its job has changed when
I called the method. Again, we need to make sure
that matches up in here. It's no longer
saying hello world. I want it to say hello
to the user's name. That's our variable called name. However, look you can see
there's a red line under here. And that's because our method here is isolated
from this method. It doesn't know
about this variable because this has been
defined inside this method, this method, it doesn't
actually know about it. That's how we can use parameters
to solve this problem. What a parameter is, we can define them
within these brackets. Right here, we're going
to type string name. Now you can see this
red line has gone away. Every parameter you
put into a method here goes inside
these open brackets, you can see this main method. Now this section right here, well that has one parameter, it's had one
parameter all along. Again, when we define
a method here, we can add our own parameters. I've added what's called one parameter and
it's called name, it's a type string. Now, inside this method, we're using this variable, this parameter, when we call our method from
the main method. You can now see there's
a red line here. When we hover over
that with our mouse, you can see there
is no argument. Now, argument is synonymous with parameter. It's
the same thing. There's no parameter given that corresponds to the
required parameter name. It's basically saying, now
this method needs a string. We can't call it
like this anymore. What we do, we take
our name variable, which is the result
of the user's input, and put it into there. And now you can see we're collecting the
user's information. We're giving this
user's information to our new method called
say, hello user. So we're giving it
the user's name. Then the code goes into here. Name now equals the value
which is being passed into it. And that's our parameter. Now we're using our parameter by outputting it to
the black window. Then the code execution
comes back out. And then we're keeping
the window open again, just so this isn't confusing. We could call this
whatever we want. We could say name of the user. We could call it ham sandwich. It doesn't matter. You can
see the red line here, because it needs to be the same. But you can see here, this
doesn't have a red line. And that's because we're
actually defining it right here. Even though the value comes
into the method here, when we arrive in here, we can call this
whatever we want. It will still have this value, but it doesn't need to be
the same name, like this. It doesn't need to be like
that with the same exact name. It can be, but it
doesn't have to be. That is something you
should bear in mind. When the parameter is passed in, the value is passed in, it's redefining a whole
new variable here. But with this value, I hope that makes sense when
we run the application. Now we're saying,
what is your name? Roberto. Now you can see
it says hello Roberto. We can run this again. We can say hello Henry. That is how parameters work
in a very simple view. One last thing, We don't have to have one parameter.
We can have a lot. We could have another one of a different type like
age, which is an integer. Now I want to ask
the age of the user. What is your age? Remember, age is an integer because
it's a number. I'll just call it age. Now we have the red
line because this gives a string and we want to
put it in an integer, which isn't going to work, but we covered this before. We're going to use, we want to convert it
to an integer which is 32 bits and then put the parentheses
around everything. Now we've converted the string from the user to an integer. We're putting it into an
integer variable called age. Now we have our red line again, that's because we have two
parameters on our method. Now, name one age. When we hover over
this red line, you can see it now requires
a string and an integer. When we call this method, we need to add this
information here, and we can use a comma. Now it's even asking, it's even telling
us what we need. Age, we take our
age, put it here. Now we have a method
with two parameters. And we're passing two
parameters into it. We're not doing
anything with it now. Let's do something with it. We're going to say age is age now when we
run the software. Let's do that.
What is your name? Harry. What is your age? I am 67 years old. Hello Harry. Your age is 67. Again, we can have ten
parameters if we want. We could have different
data types in B, all different kinds of things. Again, if you want to add more, it's just another and
how you pass them in. Again, you use A here. This is how parameters work generally with
methods in C. Sharp.
14. 2-3. Method Returns: Let's talk about getting information back
out of a method. In order to do that, we
use the return keyword. Let's look at returning
information back out of a method. We have a sample
application here. It's asking for the user's name. It's storing the user's
name in a variable, then it's saying
hello to the user. What I want to do now is
create a method whose job it is to ask for the user's name and get the user's name and
give it back to us. That's what we want to do.
Now, in order to do that, we're going to
create a new method. The easiest way is
to copy this one, delete everything out of it, and give it a unique name. Its job is to ask
for a user's name. We know how to do that.
We have it right here. We're asking for
the user's name and we're storing it in
a variable here. When we talked about
parameters before, that is how to get
information into a method. We define them here and we
pass information in from main. However, getting information
back out of main, that is what we're
looking at right now, and that's called
the return keyword. We're returning information
back out of a method, so we can use it here. When we launch our application, we're going to ask
for a user's name. We get the user's name,
put it in the variable. Now we need to throw the
user's name back out of here and then
say hello to them. Right now, we can't
do that because it doesn't understand what
this variable means, because it's defined
in our method. So we need to get this out
of here and define it here. In order to do that,
we set up what's called a return data
type by default. Here you can see there's one
on main even and one here. It's called void. Void
is like a black hole. It's like nothingness. It's nothing. But
what we want to do is return our
string variable here, back out of the method. We replace our nothingness
void with string. Now we've set up a return data
type here for this method, a string, and we want to
return this variable here. What we do, we
take our variable, we use the return keyword. We enter a white space, put our variable, and then
all lines with a semi colon. What is happening here? We're
asking for the user's name, we're stuffing it
into a variable, and then we're returning the
variable out of this method. You can see when we
return the variable here, this variable is of data type string that needs
to match our method header, which is all of this
line right here. So you can see we're
returning a data type string, which is our variable here. Now back here, we're going
back into our main method. We're calling this,
but we're not actually getting any
information out of it. We've actually done this before. You can see console
dot read line. This is a method and we're actually getting
information out of it. And that's exactly
how we do this. We can just do that and
everything works again. Remember before when I said this doesn't need to
be the same as this, we could just say
name for example. You can see it
still works because main only knows about
anything defined in Maine. Ask for a user's name, only knows about things
defined in here unless you pass a parameter in or
return something out. Let's go over this
one more time. Actually, let's run
the application. So we can see we're
running the application. What is your name? Bob.
And hello Bob. Quite easy? Well, it looks easy until yes. Let's look at what's
happening one more time so it makes perfect sense. We're running the application, we're asking for
the user's name. So the code execution goes here, there's no parameter, so we
carry on. What is your name? The user types their name, here, we're storing it into a variable
called name of the user. We're returning this information
back out of the method, which is then stored in name. That's the result
of this method. Name of the user,
We're returning it, It's the result of this method now that is stored in this
variable called name. We're then just
outputting the name to the black window and then
keeping the black window open. That is how returns work
with methods in C Sharp, remember parameters
get information in and returning gets
information back out.
15. 2-4. Method Overloading: Now we're going
to take a look at something called
method overloading. What does that mean? Let's
take a look at this example. Here we're defining
two variables here, both of data type integer called number one
and number two. What we're doing, we're
calling a method called ad, which we've created here. It takes in two
integer parameters, and it's just adding
the numbers together. It's returning the result, which is an integer
back out here. And then we're outputting
the result to the screen. Very simple. The answer
should be 20 2022. We have the correct answer. What I want to say now is what if I want to add
two doubles together? Let's turn these
integers into doubles. Now I have two doubles here. This could be 6.4 and this
could be 16.2 for example. You can see now we have
a red line under here. Because our parameters
are integers. It's expecting integers in here. But we still want this method, we still want to be able
to add integers together. I guess what we could do is
have a method called in, and then maybe another method called a double, for example. And then this would
take two doubles. Then the other one would take
two integers, for example. That's how we could get
around that problem. Then obviously, that would have a return type as a double. You can see where this is going, but what if we want to add, for example, two decimals together or two floats together? Then you can see we're
going to have to have a method for each one of these. That is quite tedious and it can really bloat
out our program. But what we can do is use something called
method overloading. What that does that
allows us to have one method but give it different parameters
but with the same name. Now, a method can have
the same name only if the parameter data types
or the number of parameters, for example, are different. Let's go back to our
previous example where we were adding two integers
together right here. What we can do then
is copy this method. We retain the same
name, for example, but in here we're
actually adding two doubles together
rather than two integers. You can see what I
have here now is two methods with
exactly the same name, except this one takes two
integers and returns an int. And this one takes two
doubles and returns a double. Now when we actually
call our method here, if I just open these
parentheses here, now we have these
little black arrows. We didn't have this
before because we only had one method with
one set of parameters. And I'll show you that now. If I open the parentheses here, you can see there's
no black arrow. We only have one definition
for the method add. But as soon as I add the
second one right here, now we have more
options available. Now we can add two integers together and we can also
add two doubles together. This is an example of method
overloading in C Sharp. It just allows you to have different options for a
method with the same name. You can see C Sharp has built in methods that take
advantage of this already. For example, when we write
something to the console, you can see if I do
the exact same thing, this method is actually
overloaded 18 times already. So you can see it's quite
a popular principle in shop programming, so I hope this helped you, and this is an example of
method overloading in C shop.
16. 3. Comments and XML Summary Tags: Now I want to talk about
something very important. If you want to make
your life a lot easier or you want to take
programming more seriously, then you need to
be using comments. So what are comments? If you have a very
complex application or a very complex line of code, it's really long and maybe you knew what
it meant at the time. But if you come back to
this a year or two later, you might have totally
forgotten what it meant or the craziness you
were typing at the time. So that is why comments
are very useful. It's a reminder
mainly to yourself, but if you're working
with a team of people, it also tells them what
the code does without them having to read and
understand all the complexity. We can do comments in
three ways in C Sharp. The first one is a one line
comment. We could do that. For example, you can see when I leave a
comment, it's green. Now, this comment here, it does not get run by the software when you
produce your software, like an EXC for Windows. It doesn't get compiled into it, so you don't waste space or
megabytes with the comments. These are really useful. Again, if you have
something really complex, it just tells you what
the next line does. So we can put comments on
pretty much any line we want. We can put them after a line. Again, they don't get run, so there's no red
line underneath. And it just really tells you
what the next line does. Generally, people
put the comment above the code and
not next to it, but you can put it next
to it if you wish. Let's just put some
comments here. You can see roughly
how it works here. I'm going to say, we know this line keeps
that black window open. So I can put a comment that says it keeps the window open. This one it says
say hello to user. I could put a comment
that says say hello. When I come back to
this a year later, and I've forgotten
everything about shop, because that always
happens with languages. You can open this and instantly know what each of
these lines do. You don't want to go
crazy with comments. You don't want every
line to have a comment. But definitely if you don't
understand something, then definitely put a comment
there because it will remind you again and you can get back into
it a lot quicker. That is a single line comment. The next thing you can do
is a multi line comment that is one forward slash
followed by an Asterix. Then if I press Enter, you can see it creates
Asterix is on every line until I end it with one
more forward slash. Now anything I type here
is all inside the comment. This is useful when you want to introduce maybe a method
or what's called a class. This is the whole thing we're
working with right now. Say you're working on a team of ten people at the
top of the file. You want to say who made it, because if there's a problem, then they can say, okay, Bob wrote this whole
section of the software. We know because the
author is Bob, then Bob, when he makes this
part of the program, he can say, I made
this, don't hate me. Then he can summarize
what it is. It's a music player, It's great, anything
he wants in there. So it's really up to you. But this is how to do
a multi line comment. They are useful for sort
identifying maybe who wrote the file and maybe
roughly what it does. That way people
don't have to read every method and try and work
out what this file does. Generally, multi line comments go at the top of
files, may be up here, so the first thing
people can see or it can go above
something very complicated, like a method or
something like that, that's generally where people would use a multi line comment. When you want to write a lot of single liners, for example, the last comment I want to talk about is what's called
an XML summary tag. Now it's not really like a
comment like this per se, but it gives you
important feedback. It gives you in plain
English feedback on what maybe the next
line of code does. But we can use these for maybe methods or
things like that. If you have a
complicated method, maybe it's like 100 lines long, it does all this fancy stuff. Maybe the name of the method doesn't really do it justice. It might say ask
for user's name, but it does lots of
other stuff in there. Maybe it returns something that might be a bit complicated or it has lots of parameters and you might not know necessarily
what they mean. We can use what's called
an XML summary tag to expand on this, where I call my method. Here I hover over
it with my mouse, you can see it doesn't really
say much. It says string. Program, do ask for user's name. However, if I har over this
one console dot read line, look at all that
information there. It's saying reads the
next line of characters, it's telling me what it returns. It's lots of different
information. I'm thinking, oh, well,
where's that on mine? How do I set that up? And that's what's called
a XML summary tag. Above our method here, do three forward slashes 12. And when you do the third one, it creates this nice
little template for us. It's in XML format. Here's the open summary tag, here's the closing one that represents the information
here which says, reads the next line of characters from the
standard input. Here I define roughly
what this method does. If someone hovers
their mouse over here, they can quickly see
what it does without having to read 100 lines
of code. For example. It's giving the other developers information on what
this method does. For example, you want to give it a very descriptive thing. Now when I hover
over this, oh, okay. It asks for a user's name. Oh yeah, I forgot I built a
secret Bitcoin miner in here. So for example, you can put
whatever you want in here, but it's for your benefit. Imagine you put your
software away for ten years. You come back ten years later. You've forgotten everything. But now you can just
simply have your mouse over here and oh, that, yeah, of course,
I forgot about that. So it's good for your benefit, but it's also good for other developers,
maybe on your team. For example, inside here
we have two returns tags. And that's just roughly
what's being returned. So we're returning
the name of the user. Remember it's, you can put a little hint in here when we get
the user's name, we're saying, oh, remember
it's only their first name. When we hover over here, we can see it returns
the name of the user, but we're reminding ourselves, it's only their first name. This is why these XML
summary tags are useful, because when you
hover your mouse over here in an instant, you know exactly what it
does in plain English. So these are really useful. And you can see this method
has a one parameter here. When I do the same thing here, we have an extra thing here. Again, we can use our summary. It says hello, say
hello to the user. Parameter defines what
our parameter does, like what information
we give to it, It will be the
user's first name. This is say hello to us. When I haver over
this we can see here, say hello to the user. When I open the bracket here, it's telling me what the it expects stre what
is that full name? Is it first name? Last name? Nickname. But when I
look down here Oh, it's the first name,
of course, Yeah. Because we're
reminding ourselves, we're telling our user, when we call our method, exactly what our method does, what it expects as a parameter, and also what it returns back. So they are the
three different kind of comments you can
use in C sharp.
17. 4-1. If and Else Statements: Let's take a look at something
new conditions in C sharp. We're going to take a look at the if statement and
also the el statement. E L S E for L. What a condition is something that is
evaluated as true or false. Take a look at this. Are
you Bob? Is your name Bob? Well, the answer is
either yes or it's no. Do you have a you either have a dog or you don't have a dog. Are you six feet tall? Either I am or I'm not. So they always have
a yes or no answer. The condition in this case is a Bob, that is the condition. You could expand this condition. Are Bob, do you have a dog? In which case? All of
this is the condition. If your name is Bob but
you don't have a dog, then the answer is no. Otherwise, it's yes if you
have both, for example, because there's an end
here, this is a condition. This is what our condition is. We deal with these every
day, multiple times. And we can represent these in C sharp by using what's
called an if statement. Let's take a look.
A very simple one. We're going to create
a little bit of software called Are you, Bob? What it does, It asks
for the user's name. We take in the user's name. If the user's name is Bob, we, we're going to give them an amazing greeting because
we really like Bob. If their name is not Bob, then we're just
going to give them maybe a standard Hello, Roberto or something like that. Take a look at the format
of the if statement. It starts with If,
that's the keyword, the open parentheses, just
like we do on a method. For example, open parentheses
inside the parentheses. Here we put the condition. Our condition is,
well, are you, Bob? We know that the name variable contains whatever
the user entered, so we're going to put name. Then we want the
equality operator that's represented
by two equals sign. When you assign
something in C sharp, we use one equal sign. But when we want to compare
something, we use two. We're saying if the user's
name is equal to Bob, then we need to do
something in C Sharp. Sharp loves these curly braces. When we have a
method curly brace, when we have an if
statement curly brace, when we open a curly brace, we always close a curly brace. You can see these ones here
match up to these ones here. That's just how the language is. This is our if statement here. This is the content
of our if statement. Everything between
the curly braces. Now, like I said, if the user's name is Bob, we want to give them
an amazing greeting. Let's try and type English. We know their name is Bob. We might as well just put Bob. Hello, Bob. These, those name is Bob are giving them
an amazing greeting. Look. However, if
their name is not Bob, maybe it's Roberto or Henry, then we need to give them
a different message. If we run this program now you can say,
what is your name? Let's type in Henry. It's giving us a
standard Hello Henry. It's actually ignoring this completely because
the name is not Bob. However, if I run the application
now, what is your name? Well, my name's Bob. And remember C sharp
case sensitive. So we only checked for a lower case barb in
our if statement, so make sure it matches
that. So click Answer. Now we've got our
amazing greeting look, but we have a problem Look. It also says hello Bob as well. So he's getting two greetings. And that's because the
if statement condition, which is this section,
is being satisfied. It evaluates to true. Therefore, this line of
code is getting executed. Once the if statement ends, we're still executing this bit. But maybe we want to reserve this greeting for
Henry, for example. Therefore, we introduce
what's called an L statement. E LSE, again, curly braces. This section is
reserved for Bob. This section is reserved
for anything not Bob. This evaluates to true when
the user's name is Bob. It evaluates to false
if it's anything else. Else, all the else
stuff goes in here. We want to give the
standard greeting to anyone apart from Bob. And that is how the
else statement works. So if this is evaluates
to true everything here, If it evaluates to
false everything here, for example, if I
run the program, now what is your name? My name is Bob. Now I get
the standard greeting, and this section is ignored completely because
my name is Bob. But when I run the program, now I type in anything, we get the standard greeting because this part is ignored, it falls to the
else section here. It cannot exist without
an if we can't do this, that won't make sense. Else always needs an
if to go with it. When we try and run it,
there'll be an error. You cannot have else by itself. It always needs an
accompanying if above it. It's a very simplistic view
on an example condition, which is the if condition
in C. I want to just run through a
quick example so you fully understand how
these conditions work. Now, when you have
an if statement, it has a condition
and an action. If this evaluates to true, it runs this section here. If it evaluates to false, this section runs here. When we talked about variables, we had a bolen variable. Bolen variables evaluate
to either true or false. What we can do, I'm just
going to use parentheses. Parentheses is optional, but I think it
improves readability. Now we're storing the result of this into a variable
called is Bob. Then we can put is Bob right here is the name given
by the user Bob. And when I say is, I mean, is it equal to the
equality operator, yes or no, true or false? Then true or false
is going to be stored in this variable
called is Bob. If statement is then ran, it's going to say is true
false. If not false. If I run the software here, I type in Bob, hey
Bob, you're amazing. It's exactly the same thing. It gives you more clarity on what is going on, if
that makes sense. I haven't talked about
Booleans that much, but it's basically saying, does this equal
to true or false? And this is either going
to be true or false because that's how you
represent it as a booling. And then when we run
the if statement is Bob will be either
true or it will be false. And it's going to run
the appropriate one. If we're not Bob, we're Henry. Then it's going to say,
hey, random person.
18. 4-2. Else If Statements: Now let's expand on our
if condition example in our last tutorial and talk
about the el if clause. Here we have our standard
greeting for Bob. But what if we wanted a
special greeting for Henry? Bob gets his own custom message. Henry might have
his own custom one, then everyone else
gets a standard one. For example, here we introduce
the else if statement. Let's go down here.
This is denoted by that we want to change Bob, because we already
have that condition. These conditions really kind
of really need to be unique. Otherwise it won't make sense. It'll be redundant really. So now we're saying, are
you Bob or are you Henry? Remember, let's make our
comments make sense. So, is your name Bob? Hello, Bob. Is your name Henry? Oh, hello Henry. But he gets more exclamation
marks because he's caller. Then if you're not Bob, you're not Henry, then you are everyone
else at the bottom. So let's type in
Henry, for example. Now we're getting the
Henry one because our name is Henry. Very simple. Once you understand how
the if and the else works, else if is just something else. Again, we can even expand on this and have another
name in here, maybe Scott or
something like that. You can modify that appropriately
to whatever you wish. That is how the elif
statement works. Again, you don't need
el, you don't need else. If quite happily have
this for example, If I type in anything else, they're not going to
get a message at all because we haven't told
it to do anything. That is the power of the el if statement when using
the if condition. Now I'm going to show you
a little bit of advice. Now, we've covered
if el if statement. That is, when you
have a condition, for example, with only one
line of code underneath. So we have this condition,
one line of code. Then this condition,
one line of code. When we have one line of code, then these curly braces
here, they're optional. What that does by removing those, it increases readability. It gives less bloating
to your software. This is exactly the same
as what we had before. However, for example, if we
have two lines of code or more under each condition,
then there's a problem. And that's because it
needs those curly braces. Right here you can see there's
a little red line there, and the error is not
very descriptive. That's because it's trying
to read all of this on one line and it's going to
throw a mysterious error. When you have one line of
code under each condition, then the curly
braces are optional. But you cannot do this
with methods, for example. Only things like if, else, if, else, and some other things
we haven't discussed yet. But that's a little
tip where you can improve your code
readability moving forward.
19. 4-3. Equality and Inequality Operators: Equality and inequality.
What are those? What does it mean? Well, these are things you might hear now. And again, we've already covered equality a little when I was
discussing the if statement. But equality is basically saying is something
equal to something else. And that's represented
by two equal signs here. But how do we say inequality? Okay, What if the
name is not Bob? How do we represent that? What we can do there is
use the not equal to, which is represented by an exclamation point
followed by an equals sign. Now, it's pretty much reversed,
this whole statement. If the name is not equal to Bob, then well, this isn't going to make sense now because
their name isn't Bob. What we can do now
is say, hey Bob. If I run the software now, what's your name, Bob? Nothing's going
to happen because we haven't told it
to do anything. But if I run the software
and put anything else, it's going to say,
hey, you're not Bob. But if I just flip
this operator into an equality symbol right there, it's going to reverse the whole meaning of the
whole statement. You can see now it
doesn't make sense because even though the name is Barb, it's still
running this. If you want to say something is equal to something,
two equal signs. If you want to say
it's not equal to, then we need not equals, which is exclamation
and an equal sign.
20. 4-4. Comparison Operators: Okay, comparison operators. I have a very simple
application here. It asks the user for a number 1-10 It takes the user's input, converts it to an integer, and puts it in a
variable called number. That's pretty much the
only thing this does. What I want to do, if the user enters a number
lower than a five, I want to say a message to the user to tell them
you chose a low number. Otherwise, you chose
a high number. Very simple. In
order to do this, we need a condition
we're going to use. The condition we're going to say is the number
less than five? How we represent less than
is a left angular bracket, that looks like
that, and then five. Then with the statement,
we use our curly brackets. Then this is what happens when our number is lower than a five. We're going to tell the user, I don't know, you
picked a low number. Something like that. However, if the number is not
lower than a five, well then we can use L just
pretty much reverse this. You picked a high number
if we run the application. Now pick a number 1-10 Remember, lower than a five is low,
so I'm going to do four. I picked a low number,
and that's it. Great piece of
software, isn't it? Then if the number is five
or higher, let's do a five. It should tell me I
picked a high number, I picked a high number. Similarly, if I put
1 million in there, it's going to say I
picked a high number. But this is an example of a comparison operator that is called the less than operator. Similarly, we could use
the more than operator, which is represented by
a right angular bracket. Now, this is not
going to make sense. We'll have to reverse these. That's going to do
exactly the same. But you can see it's reversed. If the number is more than five, then we picked a high number. Otherwise we picked
a low number, it's going to do
exactly the same thing. But because I reverse to this, I have to reverse these two. It only makes sense the other two are more
than or equal to, and less than or equal to. More than or equal to is
represented this way. More than or equal to, less than or equal to, as you may have guessed, a left angular bracket
and an equal sign when using things like
not equal to, less than, equal to, more than equal to, Try and remember that equal sign always goes on the
right hand side, always in C sharp. Now, if the user picked a number less than
or equal to five, then apparently they picked a higher number,
which isn't true. We reverse these again. Okay? Less than
or equal to five, they picked a low number, we had less than five before. If it's anything
up to number four, then it's a low number. If we want to say less
than or equal to that, we would need to
do that instead. Because the number is less
than or equal to four, then it's a low number. Less than or equal
to four is the same as saying less than five. Again, we can use more than or equal to reverse the logic. Again, if the number is
more than equal to five, again, we can reverse
these statements, we get exactly the same
thing they are what's called comparison
operators in C Sharp. If we put seven, you
picked a high number.
21. 4-5. Boolean Operators: Booling operators. It sounds a bit complicated, but I assure you it's not. A booling operator is
basically a way of saying and quite hard to say. What we're going to do
is create a sample, a basic lottery application. We're asking the
user for a number, 1-10 If the user enters
a three or seven, then they won, they've
won the lottery. Let's have a look out,
we can implement this. If you say the
sentence out loud, it's pretty much telling
you what you need to do if the user implied picks a
number which is three, a quality for three now. Or is represented by two
vertical pipes like this, 12. I don't know why.
That's just how it is. The number is equal to three, the number is equal to
seven. It's very simple. When you say out loud, it's pretty much telling you
what you need to write. Then I want to tell the user they've they've won the lottery, they've picked the lucky number, So let's take a look at this. Pick a number, 1-103 you've won, let's prove it's not a
fluke side bin number two, nothing happens, that's because we haven't told it
to do anything. That's a very basic example
of using the operator. You can use more than one. You can use four
if you would like. So if the user picks 34 or nine, for example, perfectly works. Now you have four lucky numbers. That's the operator, what's
called a Bolen operator. The other Bolen operator
is the opposite. It's the one and
that's represented by, to a persons that one
makes more sense. At least that means, but
you need two of them. With the end operator. What we can do, we can
say if the number is not equal to two and
it's not equal to seven, for example, then they've won. What we can do if the
number is not equal to two, the number is not
equal to seven, because 2.7 are bad numbers. If you choose 2.7
you've lost everything. For example, as long
as the number is not two and the number is not
seven, then you've one. That's how you can use the
operator and you can see the logic reverses to the one we've just used
with the Or operator. Now using not equal to, but the same logic applies
when we run the application. Now as long as we don't
pick two or seven with one, let's pick four. You
can see with one. However, if we
pick two or seven, it's not going to do anything because we haven't told
it to do anything. That's a very basic example of using booling operators
like the R and the end. Again, with these you can expand it and do four
numbers if you wish. And what we can do
with and operators, we can combine them as well. Let's look at a quick example
of how we can combine. And let's ask for
the user's name. We're going to ask
for the user's name and take the user's name in. Now let's pretend that Bob only has access to the lottery application that
we're doing here. He's the only one with the
authority to play the lottery. What we want to do is say
is the user's name Bob, does he have the
number two or seven? And that's an example of how
we can use and together. But the point is the
whole thing will either evaluate
to true or false. That's the main point
of the condition here. Is the name equal to Bob and does he have the
number two or seven? So I'm going to put two or
seven in parentheses here. So it's actually a
lot more readable and it's going to make sense. And it's going to calculate
correctly as well. So, is the user's name Bob? Yes. Does Bob have the
number two or seven? Yes. Let's say he has
seven then he's one. Let's say the person's
name is Henry. Okay. Is the name Henry? Is the name Bob? No, it's Henry. Okay. No, then it's just
going to skip down here, So let's test the theory. So what is your name? Henry. Then let's put a now
let's put the lucky number. I think seven is one of them. Then nothing happens
because it's not Bob. Only Bob has permission to potentially win
the lottery here, let's put Bob in, let's give him a lucky number and he's one. Just like that. Let's do
Bob with an unlucky number, which is definitely 44. Nothing happens. You can see
this is how it evaluates this whole condition with an and booling operator
and also an one. It's good to use parentheses
as well, to make sure a, it calculates
correctly, and two, it improves readability as well.
22. 4-6. EXERCISE - Building a Calculator Game: So we're going to do a little
bit of an exercise now and test your knowledge on some of the things
we've learned so far. What we're going to do is create a sample calculator in C Sharp. Right now, there's
not much going on. We're just saying to the user, welcome to our call calculator. And when we run the program,
nothing is going on. So we need to program
that ability, what the user is going to do. They're going to enter
their first number, which could be a decimal, and then they're going
to enter an operator plus minus multiplication
or division. And then they're going to
enter their second number. And then it's going to perform the calculation and display on the screen a few
things to consider. Number one, the user
can enter decimals. We need to make sure we convert our numbers to
doubles, for example. The next thing is we need to
take in the operator that the user enters and work
out whether it's a plus, minus, divide or multiplication. And then act on that
appropriately using conditions. Let's ask the user for their first number. We
know how to do that. We're asking the user
for their first number. To collect that information, we use console dot read line. We want to put this
into a double. I've set up a variable called first and that will
store the first number, but console dot read
line returns a string. We need to convert this
string into a double. We can use convert to do that, we type convert period and we want to double open brackets. Put the output of this
inside the brackets. And then remember to
close the brackets. Now we've captured the
user's first number. The next thing we want to do is take in the user's operator, but let's take in the
user's second number first. That's because we can
just copy and paste this. It's a lot easier. We have the user's
first number and the user's second number easy. Now we want the operator.
Let's copy this. The operator will be a string because console dot read line
already gives us a string. We don't need to convert
anything so we can remove this. We're going to create a new
variable called operator. But look what happens
when I do that. You see it's highlighted blue. It's throwing an
error. Why is that? That's because operator
is a key word in C sharp. It's already actually used. For example, we can't create a variable with the name
of double for example. It does exactly the same thing. That's because it's
a reserved word. We need to choose a name
that's not operator, because operator is already
used in the C sharp language. I'm just going to call it OP. You may discover that I thought I'd tell you
the information now. Now we want to ask
them for the operator. We might want to tell
them what they can do. We're saying you
can choose plus, minus, multiplication
or division. We're taking in the operator and storing it in
a variable called p. Now we have all the
information from our user. We have the numbers and
everything we need. Now what we need
to do is find out what operator they're using and then perform
the calculation. How do we find out the operator? Well, we can use if
statements to do this. We say if. Now we use
the equality operator. Is the operator. Because
the operator is a string, we use double quotes.
Is it a plus? The code inside this, if we put in the curly braces, if the operation is a plus, we say f plus second. But we want to put the result
of this in a variable. Let's define a variable
which stores our result. I'm just going to
initialize it to zero. Remember the semi colon result equals the result of
first plus second, because we're working
with the plus operator. However, what if they want to multiply two numbers,
for example, then we need an if the user enters
multiplication for example, then this isn't true,
it evaluates to false, then the code execution
will jump down. We need to catch that
here in an else. If, if the user wants to do a multiplication, then
we check for that. And then just multiply
the numbers together. It's very easy, isn't it? You can see where
this is going now. Mi takeaway and division, the division here, and
the takeaway here. This is how we actually
detect the operator here. In every case, we're doing the appropriate calculation
depending on the condition, then always putting the result in the result variable here. The last thing we want to do is tell the user what
the result is. You can see here a visual
studio is offering me this. I'll take it, Press
Tab on the keyboard, and now it's written for me. Now I want to tell the
user what the result is. Result, something like that. Let's run the program
and see if it works. Welcome to our cool calculator. What is your first number? Three, What is your operator? You can choose plus, minus,
multiplication, or division. I'll choose multiplication. What is your second number? Because we know three
times four is 12. I don't need to think about it. The result is 12. Well, that
works. Let's try one more. Let's try 200/3 because we know three doesn't
perfectly go into 200. So we can test that. Our result is actually
giving us a decimal. You can see the
result is 66.6 6667. So we have a nice degree
of accuracy here. By using doubles
rather than integers, we can deal with decimal
values and numbers that aren't integer numbers
that aren't whole numbers. This is a very quick
example on how to make a prequal calculator in C Sharp by using everything
we've learned so far.
23. 4-7. Switch Statements: So I'm going to
introduce something now called a switch statement. It's a new kind of statement that we're going to learn about. And it's very similar
to the if and else if statement in the way that
when the if statement is run, it evaluates a condition. If it's true, then it'll
run the action below. If it's false, it'll go to the next Els if statement
and try that again. If this is true, it'll run
this action, et cetera. Switch is very similar to this. It's just another way of representing the
same information. What I'm going to do, I'm
going to rewrite this as a switch statement so I can show you exactly how that works. With a switch statement, we use the keyword switch. It has one input, which is what the user
types into the program. By the way, before we start, I'll show you what
this application does. It asks the user to
enter a day of the week, and then gives a
personalized message about what day they've entered. If I run this program, please enter a day of the week. I type Monday, I dislike Monday. It's a very simple application. What I'm going to do is rewrite this as a switch statement. It takes the user's input, which we've put in a
variable called input. Just like most
things in C Sharp, we open and close curly braces and put all the
code in the middle. Now a switch statement,
for example, if statement, to check
different conditions. However, with the switch
statement it has cases. These represent, for example, an L if statement. Our first case can be
is the input Monday. We represent this like this. Then we put the code in
the middle right here. In a switch statement. These three lines
here are pretty much the same as these three
lines right here. It's just worded differently because input is a
data type string, our case needs to be a string. If, for example
input is a number, then this needs to be a
number. That's how that works. A switch statement can
have one or many cases. We're going to do one
for each of these. Every case inside a switch
statement must end with a colon and must terminate
with the keyword break. And all lines end
with a semicolon. Every case header ends with a colon and ends with a break. That's just how it is
inside switch statements. Curly braces are optional. You can put them, you
don't have to put them. You can put the break
inside the curly braces. It's very flexible
on how it works. I just tend to leave them out as long as all of
your logic here, and you can have multiple
lines of code inside a break. And the colon from the header,
you're all good there. That's our first case, Monday. I dislike Mondays
again for Tuesday, the next case would be Tuesday. Again, we can't have the same exact case because
it's redundant. The next case would be Tuesday, and we take this line
for Tuesday, et cetera. You can see a pattern
emerging here. The switch statement has lots
of conditions inside of it. Through the power of editing, I have rewritten all of those
and l if statements into one switch statement
and it will do exactly the same thing.
Let me demonstrate that. Now let's just temporarily
cut this logic out. Now I'm going to run the
application I type in Monday. You can see I'm getting
exactly the same result. This switch statement
right here is exactly the same as all of these ifs and L if
statements here. One thing you notice
is readability. It reads a lot better. You can see it's actually
a lot more minimal. You can clearly see what's going on and it looks a lot
tidier than this. That's one advantage of
using a switch statement. A disadvantage is the
booling operators. For example, if input is Monday or Tuesday
but not Wednesday, we have a complicated
thing right here. These are quite difficult
to achieve with switch statements and it
gets a lot messy real quick. In that example, I would
prefer an F statement, in that case to work with
complex bolen operators. Another advantage of using switch statements is that when you actually get
a lot of conditions, here we have seven,
it's quite a lot. When we get to five or more, then a switch statement
will actually execute a lot faster
by the system. This is just due to design. What's going on in
the background. When you get five cases, for example, or more, then I would prefer
a switch statement over this just because it's
actually executed faster. If you represent seven cases in if and else if statements, then the computer has to
evaluate every single one. It goes, oh, this
one, is it this one? Is it this one? But this doesn't work in
switch statements. It actually gets executed
a little differently. It's more performant
when deciding between switch statements
if and else if statements. Then it's just up to you. You have to take
your example and work out which one
works best for you. One thing I'm going to mention
with switch statements, one last thing is, what happens if none
of these cases happen? What if there's a magical
eighth day of the week, or maybe the user actually spelt one of these incorrectly, Then none of these cases
will actually happen. If we did this example with
if and else if we would have a final L at the bottom that
would read something like, it would read something like this telling the
user they've entered an invalid day because maybe they spelled it
wrong. For example. How do we represent this
in a switch statement? Well, we use what's called
the default keyword. If I type default, always end it with a break, just like the cases above, then I can put that
same code right here. If I remove this logic
and test the application, then purposely spell one
of the days incorrectly, you can see it's
telling the user, they've entered an
invalid day of the week. So this is quite useful
when you want some code to run where none of your cases
actually evaluated true. So it's like a
catchall, for example.
24. 4-8. Conditional Operators: Let's talk about conditional
operators in C Sharp. Conditional operators
aren't limited to C Sharp. You can actually experience
them in C plus plus and other languages what a
conditional operator is. It's a quick way of replacing
an F and an L statement. Consider this example. Here we're asking the
user if they like coffee, we're taking their input and
storing it in a variable. Then if they type
yes, for example, then we're just setting up
a variable called message, and storing this
string inside it. I knew I could count
on you. Anything else? We're saying we're no longer friends and we're outputting
it to the screen. If I just run the
software now so you can just quickly
see how that works. Yes, I knew I could count
on you. Very simple. But you can see we have an if statement here and
an L statement as well. It takes up four lines of code with this extra
can of variable here. There's five lines in total. When you develop large
pieces of software, sometimes it's nice to simplify
this all onto one line. It prevents bloating, and again, it could improve readability. It does depend how can I represent this on
one line of code? How do I minimize this? Well, we can use what's called
the conditional operator. What I'm going to
do, I'm going to rewrite all of this section here using a new concept,
the conditional operator. Now it's sometimes called
a ternary operator, that just means consisting
of three parts. And you'll see why it's
called that as well. I'm just going to write this out as a conditional operator, then I'm going to
explain it afterwards. Like I said before, it
consists of three parts. The first part is the condition, this is separated by the second part with a
question mark there. Then the second part is if the condition
evaluates to true. The third part is if the
condition evaluates to false. Now, this one line of code here does exactly the same
as all of this here. Let me prove that to you. If we do this, we run the program. Do you like coffee? Yes, I
knew I could count on you. And let's just test
the other condition. Anything else? We're
no longer friends. You can see it's much
more simplified now. We've put all of that
on one line of code. But how does this work? What happens is we're storing the result of this into a
variable called message, similar to what
we're doing here. The first part of the
conditional operator is the condition is
the user's answer? Yes, we're testing for a
string. This is the condition. The first part of the
conditional operator lives between a question
mark and a colon. That is, if the condition
evaluates to true. If this is true,
then this segment of the conditional operator is run it then this section here, if you can imagine
this queslonre, meaning else's, if it's false. And this is the condition, this variable is just
taking the result of this whole condition here,
a conditional operator. It's just a quick way of writing an F and an L statement
on one line of code. The readability, Yeah, it does depend if you can neuter
conditional operators. It may look a bit confusing, but the more you can use them, it does actually condenr
code down a lot. Consider if you have
maybe 50 or 100 of these, it's nice to simplify on just one line of
code for example. But that's how you
can write lever, conditional operators
in C Sharp.
25. 5. Arrays: So I'm going to introduce a new object type
into our learning. And that's what's called an
array. What is an array? Well, in plain English, an array is a collection
of something. For example, say
one of your friends has a nice collection
of video games. You might say, oh, that's a nice array of video
games you have. It just means a collection of something, a lot of something. In programming,
it's very similar. Let's take a look at this
very basic example here. What I have here is six
variables of type integer. Integer is the data type. I'm just outputting the first one to the screen. Very simple. Say if we emulate a
lottery application, the user picks six numbers
and then we put each of their numbers in a variable and all the variables
are unique. But what if the user
picks 1,000 numbers? Then I'm going to have to
create 1,000 variables. It's going to be really tedious. Our application is going
to use more memory, it's going to be
larger in file size, and it's going to take a really long time to develop as well. How we can overcome this problem of having all these variables with different unique names is use what's called an array. What the array can
do is group all of this information together
into one variable only. Let's take a look how we
can represent six lines of code here on only one
simple line using arrays. So what I'm going
to do, I'm going to define and initialize
an array right here. We want all our items inside the array to be
integers, numbers. We're going to use the int
datatype for our array here, then I'm going to use open
and closed square brackets. That's telling the system, hey, I want to create an array. We're going to give
the array a name. We're going to call it numbers. We've declared the
array right there. And now we want to
initialize the array, which means we want to
put some data inside it. And we can do that
on the same line. To do that we're
going to say no. Then I'm going to put
the data type again, the square brackets again. Now I want to put values
inside this array. I use open curly braces, closed curly braces,
and then a semi colon. Now inside these curley braces, I'm going to put the
values, so I can put two. When I put a next value
I use a and then 12, and now the next value, 264,556.71 Now this one variable here called numbers is an
array of type integer. These are all the
values inside it. Now this one line of code represents all of
these six lines here. Now we no longer need this. Now how do we actually access the numbers
inside this array? Well, we take the
name of the array, which is numbers, then
we use square brackets. Inside the square brackets, we put an index for our values. Now, when we talked
about substrings before, I said the index is
generally in C sharp. Start at zero, this
is item slot zero. This is item slot number 12345, even though we have six items, this is index five because
this is index zero, bear that in mind when
working with arrays and collections and things
like that in C Sharp. If I want to access this
first item, the number two, I just put zero in there, because it's at index zero. If I run the program, now you can see it's outputting
number two here, which is our first item. Similarly, if we want to
access the number 12, I just put one and I
can run the program, and then it outputs 12. So very simple, That's how you actually access the
information in the array. You use the square brackets, but you put an
index inside them. If we try and access an
item outside of our array, for example index 45, well, we only have six
items in our array. If we run the program, it's
going to throw an error. And typically the error
will say something along the lines of it's outside
the bounds of the array. That's because we don't
have 46 items in our array. It's just telling us unit doesn't exist. I don't
know what to do. One other thing you
might want to do with an array is you might
want to define the array. But we don't know
what information we want to put in it yet. Maybe we want to
define the array here, and then we want to do
some other cool stuff. And then later on, further
in the application, we might finally know what numbers we want
to put in here. For example, what we do in this case when we
define the array here, we want to put like
a capacity in here. It says here, if we actually
hover over this red line, array creation must have an
array size or identifier. Basically, it's saying, how
many items will you have in your array when you
want to use your array? I know I'm going to have six
numbers because it's like a. For example, it could be a lottery application where
there's only six numbers. We define it with a five here. If the index starts at zero, then we have 012345. By putting a five here, we're saying we're going to put six numbers in this array. I hope that makes sense. Now we've defined the array, now we still need to
initialize it because we have no values in here by default, if I try and access the
values in the array, even though there's
no values in here, it's going to output zero because this is
default behavior. What I want to do is now
put a value in the array. So I'm going to put a value in the first slot which
is index zero. And I'm going to put
the number 777 in here. Now when I run the
application, you can see, we can see the value 777 and that's how you actually
initialize an item in your array. Similarly, if I go to the next line and try and
put a value in the next one, visual studio is actually predicting what we
might want to do here. You see these gray
characters here. That's basically
saying if you press Tab on your keyboard.
So let's do that. It's going to enter that for us, which saves a lot of
time when programming. Then we can put that
in there, for example. Then we can access index one, which should be the
value 456, which it is. That's actually how to
put values in our array, because we've only defined an array that can
contain six items. Similarly, if we try and
put a value in slot 45, it's going to throw
an error as well, because we're outside
of the bounds. The last thing I'm going
to talk about with rays, the first thing before, the last thing, Rays, is one of many collection
types you can use in C Sharp. There's array lists,
lists, dictionaries. This is something to get
you started with on how to manage lots of
data, for example. The last thing I'm just
going to go over quickly is your arrays can have
pretty much any data type. We can have an array of
strings, for example. This could be people's names. Then we need to make sure
when we initialize it, it actually matches
the data type. Let's delete that now. We can put some names in here. We can put in Henry. We can put in our
friend Bob, et cetera. Now we have an array of strings. Okay, when we access our array, we can just do it
exactly like before. And there's access Henry, which is the first item there. When we run the application, you can see it outputs Henry. Remember, when you define an array with a
string data type, all the values need
to be strings. Similarly, if you have
an integer array, you have integers here.
26. 6-1. While Loops: Now for something
completely different, I'm going to introduce
looping in C Sharp. To introduce looping, I'm going to introduce
the wire loop. Consider this example. Here I have a number counter. As soon as we open the software, it's saying to the user,
welcome to the number counter. Please enter a number, 1-3 Let's run the application. When I enter the number
three, for example, it counts to the
number, I input 123. If I enter the number two, then it'll count to number two. This is represented
by these series of if and else if statements. If the user enters two, it just outputs 123123. It counts to the number
that the user enters. However, consider if we want
to modify this application and ask the user for a number
1-1 thousand, for example. Now how we would
represent this with if statements for each number, we would have this whole block. If we have the number four, then we're going to
add another else if statement here, put
in the number four. Then add another line here
where we count to number four. But if we go all the way to 1,000 then this is
going to be huge. The file size of our
software will be huge, it will be really slow to run. How do we solve this problem? Well, we can represent all of this logic here by using a loop. We're going to use a while loop. Let me write out
the y loop format. So you can see, just
like the statement, it looks quite similar. Consider the if statement,
we have a condition. If the condition
evaluates to true, then this line of code
is executed one time. If the condition is false, it goes to the next if statement and checks this condition. If that's true, it executes
this code block once. However, with a wire loop, if this condition is true, then it will keep repeating
the contents here. If I put console
right line is one. If this evaluates to true, then it will just keep
repeating this over and over and over until this
evaluates to false. That is how a wire loop
works in principle. Let's take a look at our
example and how we can modify our application
to do all of this if logic here in one
single wire loop. Let's delete all of that. What I want to do is I want this wire loop
to keep looping, looping, looping, and outputting the number up to the
number that we input. This is the user's number
that they're going to enter. And we want the
wire loop to keep looping till this
number is reached. Okay, how do we do that? I'm going to introduce a new variable and I'm
going to call it counter. And I'm going to
initialize it to one. What counter will be? This is the number that's going
to keep incrementing 123 all the way up to the
number that the user gives us. What I want to do is output
counter to the screen. Every time this wire loop loops, I want to output the
value of counter. It starts at one
and then I want to increment counter
by one each time what I could do is equals itself plus one counter
has the value of one, but now I want it
to equal itself, which is one, and
then add one to it. Now after this, counter
will equal two. If it runs again, counter
will equal 34, et cetera. Now, anytime you add
one to a variable, you can do it this way or
you can do it this way. Just like that. This plus plus adds one to
the current value. That's just a shorthand
way of typing this. It's exactly the same thing. It doesn't work
with two, only one. If you want to
decrement it by one, you use negative,
negative and that will subtract one
from its value. But we just want to add one. Every time this wire loop loops, it's going to
output counter one, It's going to add one to it and then it's going to
go back to the start, check the condition,
If it's still true, it's going to execute
these two lines of code. Again, that's how
the wire loop works. It's going to keep looping, but now we need a condition. The condition should
evaluate to true until it gets to whatever
the user entered, and then it needs to escape from the wire loop and carry on
with the rest of the software. What condition can we put
in here to make this true? Well, we want to count
to the user's number. Including the user's number. What we want to do is
say while the counter. Is less than the user's number, then repeat this code. However, we want to include
the user's number as well. When it finishes counting, it will be less
than or equal to. Let's just run this application real quick so we can
take a look at this. Now, enter a number
1-1 thousand. Let's type in number seven, for example, and press Enter. You can see here it counts all the way to seven
from number one. That's essentially how
a wire loop works. If we run the application
again and type in 1,000 it counts all the way to 1,000 and then stops
at 1,000 You can see with not much code at all, we can replicate all of those
if and else if statements. In a very simple wire
loop such as this one, just so we're 100% clear, the software runs,
it takes the number from the user counter
is initialized to one. This is now one, while one is less than or equal to whatever number
the user put in here. Let's say the user typed in 44, while one is less
than or equal to 44. Continue this code
execution output counter to the screen,
which will be one. And then increase
counter by one. Now this is going to equal two. Now counter equals two. Yes, it's still less than
or equal to 44 again. Now counter equals three, it's still less than 44. Keep continuing this.
Once counter equals 45, well 45 is not less
than or equal to 44. What happens is it
breaks out of here, jumps to here, and continues with the rest of the program. That's essentially how the
wire loop works in a shop. I want to talk about
something very important. Now we're introducing loops. With wire loops and
any other loops we'll talk about in the future. There's a real danger of
loops looping forever. They're just endless loops. What happens when you get
an endless loop is it will slowly eat up the memory in your system until either
there's no memory left or something overflows or something
catastrophic can happen. This is a real danger here. Let's take a look at
a very small example. Remember with if statements, there's a condition here. If that evaluates to true, then it's going to
run this code right here that may just
write true in here. What happens is this
is always true, is always going to evaluate to true because I've
written true there, nothing is changing
this in this code. Even Visual Studios
grade this out because it knows it's just
going to loop on this forever. This is a very basic example. Of course, this can be
achieved by using variables that never reach
their expected value. For example, this
will just continue to run forever if I
run the program. Now you can see it's
just endlessly counting. And what's going to
happen is either this number is going to grow
too big for its container, or we're going to run out
of memory on our system. But essentially this loop
will just never end and something will cause
this program to crash. So it could be memory,
it could be anything. And usually it's something
very unexpected. So this is an example of where a loop can potentially
loop forever. This is quite common, and
this is why we have to test software to make
sure this doesn't happen, but now we're introducing loops. This is a real danger
that can happen, and it's something you should
be aware of moving forward.
27. 6-2. Do While Loops: I'm going to introduce
a variant on the Wile loop
called the Il loop. There's a very subtle
difference between the Wile loop and the Il loop. The difference is
that in a Il loop, the code inside the loop is executed at least once.
What does that mean? Let's consider this
sample application here. Welcome to the number counter. We get a number from
the user, 1-1 thousand. Then from one we output
in increments of one, the numbers up until
the user's value. If the user enters seven, it counts to seven and then continues with the
rest of the program. We can use what's
called a Wile loop to achieve pretty much
the same thing here. When we reach the wire loop, here we have a condition. The code executes this, this, this, then it
gets to this wire loop. If this condition is
false from the get go, then this code will
never be executed. The whole wire loop
will be skipped if this condition is
false and the rest of the software will continue
to run with a i loop. Now, this is not the case, that is because the condition
in a loop happens once. The loop has already executed at least
once. Consider this. Now, this does exactly
the same thing as the other piece of code. The software executes,
this line of code is run. This, we get the user's input, we initialize this variable. Now we reach this
statement, well, nothing is preventing
us from going in here. This is ex, this
is executed this. And then we have our condition. These two lines of
code have already been run before we
get our condition. And the condition says, is the counter less
or equal to number? Now, if this is false
from the get go, I could even type false in here. Then these two lines of code they've already run,
they've already executed. Even if the condition is
false, these still run. And then we continue with
the rest of the software. Consider this example. It doesn't matter
what I put in here. Now you can see as output
one at least one time. That is because these two lines
of code have already run. Even though the
condition was false. A wile loop is
useful when you want the code in your loop to
run at least one time. If you don't, then consider
using a Wile loop instead. But both can achieve pretty
much the same result. But that is the
difference between the Wile and the Wile loop.
28. 6-3. For Loops: I'm going to introduce
a different loop now called a four loop. A four loop is just another
way of achieving a result. It has advantages and disadvantages depending
on your application. Consider this example here, where we ask the user
for a number and it just counts to that
number using a Wile loop and outputs every number along our way With a low four loops
are slightly different. You see this Y loop here, we defined a variable
just above it, and then we increment
this variable by one every single time
this wile loop iterates. When the condition is
false, it breaks out of it. You can see here we've
added some extra stuff to the wire loop in order for the wire loop to
achieve its goal. Now a four loop, it has an in built mechanism which includes a
counter just like this. It's going to simplify all of this code into 14 statement. Now, what does all that mean? Let me explain. We start a four loop with the four
keyword just like that. Then the header is in brackets, just like the wire loop. And then we have
the curly braces. The header for a four loop, it actually has an extra
little bit of information. The wire loop here we
have the condition, that's the only thing
we have in here. But the four loop,
it actually requires the definition of the counter and the increment
of the counter. The header requires
three things. That's because the
four loop manages our counter for it needs to
know about this information, but it also needs to
know the condition. And that's how we enter
and exit the four loop. For example, just
like a while loop, it needs three pieces
of information. I'm going to use exactly
the same names here, maybe with a number
one afterward. I can't use variables
with the same name. I'm going to copy where we
initialized our counter here. I can't have the same name. I'll just put a
number one after it. The next thing I need
is the condition. We separate these three
items using a semicolon. Then I put the condition again, I can't have the same name. Then the last one, I
need the incremental, again, I can't have the same
name as the wire loop above. Now, this is basically exactly
the same thing as above, apart from this line here,
which I'll put here. Now, this block here does exactly the same
thing as all of this. Here you can see
the advantage in this case of a four
loop over a wire loop. That's because it keeps track of our counter fours automatically
behind the scenes. Every time the four
loop iterates, this counter is incremented
by one every time. If we want to, we could
increment it by two every time we go counter equals
counter one plus two. And that'll increment the
counter by two every time, for example, we could increment
it by eight every time. It's really up to us what we want to do with
the incremental. But typically you'll see people increment it
by one every time. There are certain cases
where you might want to decrease the value
by one every time. It's really up to you,
that's our increment. The third item, the middle
item is our condition. So it's exactly the same as
a wire loop in that case. The first item is where
we define our counter. So we need to say, hey, we're setting up a new variable and we initialize it to one. In this case, we can initialize
it to zero if we want, but we do have to initialize it. We can't leave it blank, we initialize it to one. In this case, this will do exactly the same thing
as this piece of code. Here, let me just
demonstrate that. Now here's our loop. We're going to enter
the number seven. Why not? You can see
it counts to seven. Now I'm going to remove our
while loop completely and put in our broken
down four loop, a lot less lines of code. I'm going to run
the application, I'm going to put
the number seven, and it does exactly the same
thing as the wire loop. It's pretty cool, isn't it?
29. 6-4. For Loops vs While Loops: You have to ask yourself
the following question. If a four loop has all
this simplification, it has inbuilt,
incremental here. Why don't we always use this? Why even bother with a
wire loop, for example? Well, generally, four
loops are used when we know how many times
the loop will iterate. For example, when the
user entered that number, we're counting from one, we're incrementing by one, and we're escaping the loop when the counter is less
than a certain amount. This section here
will output numbers 1-10 every time it
increments by one. And when it's
finally not less or equal to ten anymore,
it's going to escape. However, with a wire
loop we can do that, but wire loops are
better when we don't know the number of
iterations beforehand. For example, am I hungry? Let's initialize a booling
variable called am I hungry, and set it to true
because I'm hungry. Now when we enter the wire loop, we don't need to know how many
times it's going to loop. We don't need to keep track of a counter or all of this
stuff, we don't really need. The only condition we have here, for example, is am I hungry? Well, yes, true.
Okay, it's true. Then inside the wow loop, we can call a method
called eat food. And then we can check
if we're hungry again. And then we can keep looping. Finally, once we've
eaten enough food, I'm no longer hungry anymore, then I can escape out of this. But I don't know how many times this loop is going to
loop until I'm full. So it's an unknown. So this is why wire loops
are good for this because we don't know how many iterations
it's going to happen. But we figure this out
inside the loop itself. This is why wire loops are good. The number of
iterations is unknown, and this is why four
loops are good. When we actually know the
number of iterations, we can simplify this a lot
easier with a four loop.
30. 6-5. Foreach Loops: I'm going to introduce
a new loop now, and it's called a
four each loop. Now, the advantage of a
four each loop over, say, a four loop, is that it
improves readability. And it works with collections a lot easier. Now, what
does all that mean? Well, let's take a look. I have a sample application here. I'm setting up an array. It's an integer array, and the array is called numbers. I'm initializing the array with all of these numbers here. All of these numbers
are going to be inside this variable
called numbers. I'm now using a four loop, which is going to cycle
through every number in the array in turn and then
output it to the screen. Let's run the application here. You can see here the application contains each of the
numbers in our array. We're just cycling
through our array and outputting each
number along the way. We use the length property of the array to set up a
condition for that. What I'm going to do now is
introduce the four each loop. The first thing I said was the four each loop
offers readability. Let's take a look at that now, when setting up a four each
loop, we use the keyword. For each, we have
the parentheses, just like a normal if statement. Four statement y
loop, for example. Then we have the
familiar curly braces. Let's have a look at how
a four each loop looks. I'm going to do exactly
the same as the four loop. So you can see it represented
as a four each loop. In the head of the
four each loop, I set up a variable, I say in numbers. Then for each iteration
of the four each loop, I want to output
the variable num. Now, what does all this mean? Well, for a start, you can see the readability is a lot better. There's a lot less code here. It looks a lot tidier, smaller, and it's less bloating. But how does it work? What
happens here in a four loop? You can see we set
up a variable here. Each iteration we can make use of this variable right here. This is the same in
a four each loop. For every time this iterate, this variable will equal the
next value in our array. The first time this runs
the first iteration, num is going to equal one. The second time this loops, num will equal four. The third time nine. For example, in a four loop, this is equaling the index. Because we're just
counting from zero, we're incrementing zero by one and we're
terminating it when num is equal to or more than the length of the
numbers in the array. However, in a four each loop, this variable here
is actually equaling the values in the
array, not the index. The index is 0123. But in a four each loop, Numb will equal the actual
value, 14912, et cetera. We're just outputting
that to the screen. You see here we're using
an index in the four loop to access the number
behind the index 149. But in a four loop,
it actually is set as the value
num is the value. We're just outputting
the value to the screen. Let me prove that to you
if I run the application. Now you can see it's outputting all of the
numbers in the array here. The second thing I said was it works with collections
a lot better. Now we've used a standard
array like this integer array, but there are a lot
more array types and collections in C
Sharp for example, like lists and various things
like that for each offers a better readability
with those and it gives you more options
to work with them as well. That's the benefit
of a for each loop. You can see as it's
a lot more readable. We don't need to define this variable here and
keep track of a counter. It's a lot simple
in that regard. That is, another loop in sharp, and it's the for each loop.
31. 6-6. EXERCISE - Draw a Cube: I'm going to test
your knowledge now. Now we've covered some loops. And we're going to draw a
cube. What does that mean? Well, for example, if the
user enters the number five and we press Enter,
it draws the cube. You can see there's five Asterix
is across and five down. If the user enters six, then it will be six
across and six down. How do we accomplish that? Let's take a look
at the code here. Now, it's not doing
much right now. We're asking the user
to enter a number, and then we're
storing their answer into a variable called num. We're not doing anything. How do we approach this problem? How do we draw these cubes? Well, we need a mechanism to
keep drawing Asterixes on the screen until we
reach the user's number. When something keeps
doing something, we think loop in our head. We need something to
keep doing something, we need something to keep
looping in our head. We should think, okay,
we need a loop here. I'm not sure how many loops
or what kind of loop, but I know I need a loop, So that's a good start. Now, when I talked about four
loops versus wire loops, I said a four loop is good when you know how many iterations
it's going to do. You can use a wire loop, but I'm just saying a four
loop would be better. In this case, we do know how many iterations because we have the number that
the user entered, which will be the
size of the cube. A four loop would
be a good start to no approach this problem, let's start creating a four loop using the four key word here. Now the format of the four
loop. It takes three things. We need to initialize
a variable. I'm going to call it y, I'm going to
initialize it to zero. Now we need our condition. I want it to keep
looping until it's less than whatever
the user entered. Then I just want to increment
it by one each time. Now I want to output an
Asterix on the screen. Let's delete that and
put an Asterix in. Let's run our program and
see what we have so far. Let's enter the number five. You can see we have the
Asterix going down. We have five Asterix. They're all going vertically. We have it halfway
there right now. But what we need to do is get the Astrixes going
across as well. Every time this
four loop iterates, it's drawing an Asterix and
going to the next line, drawing an Asterix,
going to the next line. Every iteration
we need some put. Asterix is going
this way as well. Every time the loop iterates, how do we get something to keep doing something?
Well, that's a loop. What we could do is put
a loop inside a loop. Let's take a look at that. We can't have the same
variable name twice. You can see y is
used by this loop. We're going to need
to rename this one. Let's call this one X
for no real reason. It can be whatever. It can be cheeseburger if you
really want it to. Now we have two loops. We have what's called
a nested loop. A loop inside a loop. Every time this loop iterates, it's doing all of
this. Consider that. So let's kind of run the program now and see what
we're dealing with. I enter the number five and now, wow, what is happening now? We have 25 stars going down. That's a bit wrong, isn't it? Why is it doing
that? That's because every time this loop is run, it runs this loop. And every time this loop runs, we're actually writing
the Asterix here, but also a new line. And now that's a problem for us. We don't want to write a new
line every time this runs. Otherwise we're just going
to get vertical Astrixes. What we can do, we can introduce a new method called, right. What that does, it writes
everything in this string here, all of this stuff here. But it doesn't put a
new line afterwards. It keeps it on the same line. That's the difference
between right line which writes this and
then puts a new line. However, right just writes this and it doesn't
put a new line. Let's take a look at this. Now let's enter number five. Now you can see,
oh, all the Asterix are going across the X axis. Now they're all going across
what is going on here. Well, that's because
we're not actually writing any lines at all now. It's just pretty much
writing one way. I need to start putting
those new lines in. Right now we have 25
Asterix is going across. I want a new line
every five of these. Now we know if the user
enters the number five here, This inner loop will
iterate five times. Once it's done its fifth one, the code will finish this
loop and continue running the rest of the code until the first loop starts
all over again. Right here, I need
to enter a new line. How do I enter a new line? There's lots of ways, but using the knowledge we already
know, we can just do that. We're writing nothing. But then it adds that line
afterwards. Let's run this. Now let's to the number six, just so we prove
it's not a fluke, it's actually going to grow a bigger cube for a
different number. Now we have 123456
across 123456 down. We've pretty much done it. Let's just go over
this code real quick. We can take the user's number. Now we have a nested loop. The first time this
loop iterates, it runs this code here, which is also another loop. Now it goes inside here and outputs an Asterix
to the screen. For example, if the user
enters the number five, let's replace that.
It's more readable. It's going to run
this five times. Now we have five
Asterix on the screen. Once this loop is finished, now the loop has ended. Now we're going to print
a new line on the screen. We've entered a new line, it's going to look like this. Now we're starting our loop for the second time, the main loop. Once this is started, it runs this loop
again five times. Now it's going to
look like this. Once the loop is finished, it prints a new line. Now it's looking like this, then it goes back to the top. That's how it works, so you can visualize
what is going on here. The answer to our problem. If we want to cube
and we want to draw Asterix is going
down, then one loop. But if we also want them
to go down and across, then consider something
like a nested loop. That's how we can tackle this problem using
loops in sharp.
32. 7-1. The break Statement: So I'm going to
introduce a new kind of statement called
the break statement. Now when we talked
about switch statements here we briefly covered
the break statement, but not really in any
significant detail. But now I'm going to explain
exactly what this does and how it works and how it
can actually benefit us. Break is key. When using a switch statement, what happens is the user, for example, enters
a day of the week. We store the answer
into a variable. And then if they, for example, enter Wednesday, then this
line of code is run here. Once this line of code is
run, this break statement, it escapes out of
this switch statement and the control flow of
the application continues. What do I mean by control flow? Well, when we launch
our software, the main method is
run automatically. And then the first line of
code is run, the second line, and it's sequential, it
runs all the way down. That's the control flow, that's how your
application is run. But the thing about the
switch statement is when the control flow reaches
a break keyword here, rather than executing
the next line, the next one, the next one, the next one all the way down, It hits the break keyword, then it immediately skips everything after
it then continues. That's the power of
the break statement when used in a switch statement. Let's have a look how
the break statement can be used in something
like a wire loop. Let's take a look
at a simple example here what we're doing, we're asking the user
to enter a number. What this program does, the simple program, we're just counting up to that number. If I run the program here and the user enters
the number eight, we're just counting
to the number eight. Very simple. We're using
a Wile loop to do this. We have a condition here. We're saying if our
counter is less than or equal to the
user's number output, the counter then increment the counter by one and
we're just looping that. It's very simple how it works. Sometimes when creating a loop, like a wire loop for example, or even a four loop, you
might not have a condition. In this case, we
set up a condition because we know what the
user is going to enter, and we're counting up to that. But in some cases we
don't have a condition. We can't have a condition. We might not know what
the end goal is and we might actually work
out the end goal inside our wire loop. You know, something might be
figured out at a later date. For example, if
downloading a file from the Internet and we
download the file in pieces at a time and we might not know the file size of
the file we're downloading. So in that case, we can set
up a wire loop and just keep looping forever and ever and ever until the file
is downloaded. In cases like that, we
don't have a condition. So what we can do here is set up a condition which
is always true. What this is going to do is loop indefinitely until, for example, we've downloaded all of
the file and then we can escape out of
the loop manually. This can be quite common as well in the case
where we don't have a condition and we just have this wire loop loop
in indefinitely, what we can do is break out of this wire loop to prevent
it from looping forever. This is a good way of
using the break keyword. We can use it in
switch statements, but we can also use it where we have an
indefinite condition, which is always true. For example, let's take
a look at this example. And what I'm going
to do, I'm going to rewrite it using a
break keyword instead, and it's going to do
exactly the same thing. Let's say we don't have a
condition for this wire loop. It's going to loop indefinitely. We need a way to
break out of here, so we're not stuck
in an endless loop. What we're going to say
is if the counter at any point is greater than
the number the user entered, then break out of the loop. You can see as soon as I
typed that break keyword, this wire keyword
also highlighted, and that's Visual
Studio helping us out. For example, we could have a wire loop inside
another wire loop. Inside a four loop, we can have cascading loops. And it can be quite confusing
when using a keyword. Break Visual Studio
is just saying, okay, you've typed the break keyword, this is the loop
that it's linked to. And this is the loop you're
going to break out of, just like the switch statement. For example, this
break keyword will prevent this wire loop
from repeating forever. It's literally saying, okay, this condition
evaluates to true, let's get the hell
out of this loop and continue with the
rest of the program. The brake keyword is controlling the flow of execution
of the code. It's basically saying,
let's get out of here and continue with
the rest of the program. That's what the brake
keyword essentially does. Let's run the software and just confirm it does exactly
the same thing. Let's enter the number
eight for example. You can see it's counting
to the number eight. Using the brake keyword is another way of accomplishing
the goal before, but it's commonly
used, for example, when you don't really
have a condition and you want to
escape out of a loop. That's the power of the
brake statement in C sharp.
33. 7-2. The continue Statement: The continued
statement, what is it? What does it do? Now I've
explained the break statement. And a break statement just
as a refresher breaks you out of a loop completely and continues with the
rest of the program. Break statements can
be used in four loops. While loops, four each
loops, all kinds of loops. Just to escape out of the loop, It's not looping indefinitely. However, the
continued statement, what that does is just skips
one iteration of a loop. What I'm going to do, I'm
going to show you how the continued statement
works in a four loop. Consider this example. Here, I'm asking
the user to enter a number on what
I'm going to do, I'm going to count
to the number ten, but I'm going to skip whatever
number the user enters. Let's take a look
at this example. So I'm going to enter
the number six, and you can see the result here. I'm counting from zero, I'm going all the way to ten, but I'm skipping
the user's number. The number six. It goes
5-76 is being skipped. I'm using a four loop
to accomplish this. I'm counting 0-10 I'm
using a variable called. I'm saying if the counter is not equal to the user's number, then just output the
counter to the window. A little bit of trivia for you, if you've heard of the
C programming language. And plus, plus, we've talked
about the incrementa before, where you add one to a
variable, you put plus, plus. You can see now this is how, where plus plus came about, the programming
language C plus, plus, It's just one more
than its predecessor. That's pretty cool, isn't it? If you've ever
wondered about that. Anyway, how can we accomplish this using a
continuous statement? Let's take a look at this. I'm going to rewrite this
using a continuous statement. I'm going to say if the current counter is equal to the user's number,
then continue. This is going to do
exactly the same thing. This right here,
let me prove that. Let's enter the number six. Again, you can see
it's actually skipped the number six. How
does this work? One thing you'll notice when typing continue or
hovering over it, just like the brake statement, it's telling you which
loop it's tied to. We've written
continue. It's saying, okay, we're tied to
this four loop here. For example, if the
current counter is equal to the user's number, then continue. What
continue does? It prevents the rest of the content inside the
loop from executing. As soon as it's run
this continue here, it's going back to the start of the four loop and
continuing down. This code here is never run. Even if I have lots of code
here, all of this here, if this continue statement
is ever executed, all of this is ignored and the control flow goes back
to the start of the loop. We continue down.
Again, it's modifying the flow of execution just
like the break statement does. But how the break
statement breaks out of the loop completely
and continues the continued statement
just prevents the rest of the current iteration of
the loop from executing. And then it goes
back to the start and then continues
looping as normal. That's the difference between
the continued statement and the break statement
I can show you. Now if I remove that
condition completely, this four loop will just
pretty much do nothing. Because this code
here is unreachable. Even visual studio
is graded out, telling you that this
is never going to be executed because we don't
have a condition here. Every iteration of
this four loop, we're just hitting this
continued statement. And it's just going
to keep going back to the start in this
tiny loop here. So that's the power
of the continued statement in C sharp.
34. 8-1. Exception Handling (try, catch, finally): Now I want to talk about error handling or
exception handling. They're synonymous
in the world of C sharp when dealing
with exceptions, these are outcomes
that you don't expect. If you look at exception
in the dictionary, it's a person or thing
that is excluded from a general statement and more significantly it
doesn't follow a rule. Take a look at this
example right here. We're asking the user
for two numbers. We're putting their input, which is a string, into an
integer variable right here. And we're using the
method to int 32. To accomplish that goal, we're taking a string,
converting it to an integer. The second thing we're
doing here is dividing the two numbers together and putting it into a
variable called result. Now this program,
it's quite flaky. There's a couple of errors that can occur if we're not careful. Errors can generally occur
when we're dealing with users because users do things
we just do not expect. Sometimes if I run
the application, enter your first number. Now what if the user
just types hello? What if they read it incorrectly and put their e mail address? Users can do anything. What if they accidentally hit Enter and don't
put any number? There's lots of
things a user can do to potentially
break your software. These are called
unexpected things if I type in a lot of
letters and hit Enter. Now you can see here we have this nice little
error message here. It says exception unhandled. That basically means, okay, an error has occurred, an exception has occurred. And it's unhandled, which means we're not doing
anything about it. The computer cannot do
anything about this error because it's trying to
convert this into a number. It just cannot do it. It
doesn't know what to do. So we need to tell the system how to handle this
type of error. If I look at this software here, this error happens when
we take the user's input, then try to convert
it to a number. If I hover over
this method here, which we're using this method, to 32, you can see
this dialogue appears. It tells us what
the method does. It tells us what the method
gives us back as a return. But also there's
this extra piece of information at
the bottom here says exceptions. Now these are the two possible errors that can occur when using
this method to 32. The first one is
format exception. That's the error that
we just experienced. We type in a word for example, then it's throwing what's
called a format exception. That's because the
format is not correct. It's expecting a number, we have some letters,
the format is wrong. The other error is an
overflow exception. I'm guessing that's when you enter a really
large number and it can't physically fit it inside the data type
which is an integer. Now 32 bit integer goes
to around 2 billion. If I try and put in 5 trillion, then it would probably
throw that other error, which is the overflow exception. What we can do about this is handle these types of errors. When the computer says, oh, you've given me a word, I wanted an integer, I can't convert these
words to an integer. We can intercept this and say, okay, the users
entered some words. Now I'm going to tell
you how to handle this, this is how you
tackle this problem. The second error that can occur
is when dividing by zero, we take the two
numbers from the user. Assuming they've entered
two valid numbers, we attempt to divide
them together. However, if the second
number is a zero, then another error
is going to occur. If I put zero, now we
have another error. Now it's unhandled again because we're doing
nothing about it. And this type of error is a
divide by zero exception. The message we're trying
to divide by zero. The computer cannot
physically do that. It doesn't know how
it mathematically, it cannot divide by zero. But we're not telling it how
to get around this problem. That's the aim of this
tutorial right Now I'm going to show you how
we can handle exceptions. Now this subject
goes quite in depth, but we're just going to
scrape the surface here. What we use here is a
keyword called tri. It's quite simple, DRY
like most keywords. We have our familiar
curly braces. We end a curly brace here, what Tri is doing is saying, can you try to do
something for me please? Because I have a feeling an
error is going to occur. We know that because when
we hover over this method, there's two possible
errors that can occur. Because we're asking
input for the user, we know there's a sign
of trouble coming. We're basically saying,
please try this. That's how the tri
keyword works. We're trying something. Now what happens if this fails? A try will either succeed and
the program runs as normal, or an error may occur. That part the catch keyword. Again, curly braces,
just like before. Now, a try cannot
exist without a catch. If I remove the
catch keyword here, then we'll get a red line. If I hover over that, it says expected catch. Or finally, let's put that back. Red line has gone away. It's happy in this
catch section here, this code will run if
an error occurs here. This is telling the system
how to handle this error. Let's just say an
error has occurred. Let's tell the user an
error has occurred. Very generic. I think
if I saw this error, I would be annoyed as a user because I have
no idea what it means. It's very generic, but we
can expand on that later. Let's just see if it works. Enter your first number, let's put some words or letters. Now you can see we
have a generic error. Error has occurred now. Our software hasn't crashed,
so that's a good thing. But it's not really telling
as much information. We just get this
generic message. We don't know why occurred, we don't know what went wrong. It's not very useful to us, but at least our
software hasn't crashed. So that's a good sign. Now let's take a
look at how we can give better feedback
to the user. We don't want to tell
them an error has occurred because it's not
really useful information. The user cannot then go back and work out
what they did wrong. What we can do here
next to catch is open and close
parentheses and type in exception and
then give it a name. This can be anything,
it could be EX, you can call it what you want. Basically it's a
variable we're setting up the data type is
of type exception. Just how we have
a data type int, This one is exception. Now we'll cover what's
called a class later on, but don't worry
about that for now. But now we've defined
this variable called E, which is of data type exception. We can use this to get some
information about our error. What I'm going to do here is when we join
strings together, we use a plus here. I'm going to say message message is a string property of this
exception variable here, it's going to give
us some feedback, The error message that explains the reason
for the exception. Now if I run the application now and enter the first number, which is a lot of letters, now we have a bit more
information, error has occurred. The input string was not
in the crack format. Now, when the user reads this, they can think, oh, okay, yeah, I read the question wrong, I thought it was asking for my e mail address or
something like that. So now we're providing useful information
back to the user. Now, what if we
want to customize? What will happen? Depending on the type of error that happened. Now remember there's a couple of problems with
this application. A couple of things
that can occur. Number one, the user can enter some letters and it can't
convert it to an integer. We've looked at that now. The other one is we
attempt to divide by zero. But what's happening
here is we're just doing this
one line of code. Whatever happens here,
error is happening. How can we customize this? Maybe tell the user they've
done something wrong. If they accidentally
enter some letters, then maybe do something else. If we divide by zero, what we can do here is catch different
types of exceptions. If I copy and paste this, I'm going to put it here twice, and I'll explain why soon. The first exception here that can happen is
the format exception. What I can do here is catch the format
exception right here. What will happen here is if
a format exception occurs, any error to do with formatting, We can say to the
user, I don't know. We could give them a
really sarcastic message. We could say, learn
to read properly because they blatantly
didn't read the question. Which was to enter
a number and then they enter their e mail
address, for example. The other one was
divide by zero, okay? So divide by zero exception and the message I might
want to give the user, hey buddy, you cannot
divide by zero. What you doing then if it's not possible error and
it's not possible error, then this is generic one. When we had that if
statement, we had, then finally we had
an else at the end, similar with the switch
statement, We had the case. Then at the end we had default. This is what that is
aiming to do here. So if none of these
errors occurred, we always have our little
safety net at the bottom that just spits out a message
here in the real world, you probably won't have
just a message here. You would probably
have the system log these errors differently and
these errors differently. But this is just an example. So you can see now if
I run the application, I put in a word, It's now telling me to learn how to read properly.
Charming, isn't it? Now, if I enter two numbers, I try and divide by zero. Hey Bird, you can't
divide by zero. So now you can see it's two different things depending
on what error occurred. The last thing I want to talk about is the finally keyword. Now the finally keyword
goes with a tri keyword. It's optional, you
don't have to use one, But it can be quite useful. Let's take a look
at how it works. Finally, we'll either go after or after all of the
catches after the try. If an error occurred, all the code in this finally
block will be executed, even if an error occurred. If an error didn't occur, then this will
also get executed. It's quite useful
maybe if you work with a database or what's
called threads, and you can close
out connections or finalize anything that's
really what it's for. But in our small example here, we can just thank the user
for using the program. For example, I'm thanking the
user for using the program. Let's take a look
at this real quick. If I use the software,
enter something invalid, we're telling the user to
learn to read properly, then saying thank you
for using our program. That's pretty
sarcastic, isn't it? Now, let's enter
some valid numbers. Now we get an actual result. Here you can see the finally block is
still getting executed. Thank you for using our program. You can see finally is run regardless of whether an
error occurred or not. Like I say, it's optional,
you do not need this, but it can be quite
useful, that is, how to catch and handle exceptions when
working with C sharp.
35. 8-2. 2D, 3D and Multidimensional Arrays: I want to introduce
the concept of two dimensional
arrays in C Sharp. What we've looked at so far is a standard one
dimensional array. By default, an array in shop
is considered one dimension. However, what if we want to simulate maybe a chess
board, for example, where we have eight
squares going across but eight
squares also going up. Then we can refer to those
squares in the chess set, like a grid system with x
going across and y going up. We can simulate
this using what's called a two dimensional
array in shop. Let's look at this example here. We've just defined some
numbers here and we're storing them into an
integer array called Numb. And we're just outputting the first number in our
array to the screen. If I run the application, the first number in
the array is one, which is correct because
this is the first number. I'm going to show you an example of a two dimensional array. Now this is our one
dimensional array. I'm just going to
remove some numbers. The example isn't long winded. In order to turn this
one dimensional array here into a two
dimensional array, I use a comma inside these
square brackets here. Now that is telling
C sharp, hey, I want to create a two
dimensional array right now. This is how we
visualize our array. It looks something like that. But what I want to do is create a two D array which is
going to look like this. Because the nature
of two dimensions, you have one dimension going
across and one going down. And then it fills out into
like some graph paper, a chessboard,
something like that. This is what we want
to emulate here. Now I've put in commas here, we immediately get a red line because C sharp knows we're
creating a two D array. But this format is incorrect. The format for a two D
array looks like this. The outer curly braces here is the container
for everything. Then inside each set of curly
braces is each line here. If I copy this and put
that in there, copy that. Put that in there.
And copy that. And put that in there.
Now this initialization here of the two array pretty
much looks like that. This is the same as that. That's how you should
visualize this. Now, how do we actually
access these numbers? Again, this format is wrong. If we hover over it, we can see here, wrong
number of indices. That's because it's
now expecting two. Because we've created
a two array here, what we can use is
just the comma system, for example, 00. Now that will actually output the first number in
the first block. Here's the first block, here's the second block. Here's the third block. Again, all indexes
start at zero. This is the first one represented by the first
number here, zero. The second number here, This is the number of the
item inside the first block, which is the first one
there, which should be one. This should output
number one right here if we run the application
there, number one, If we change the second
digit, for example, two, then 012, it should output number three as
you can see there. If we increase this to two, then it should out here, because it's two
across and two down, we should get number nine. There we go. That
is how to access information from a two
D array in C sharp. Now you may be asking the
question, what about three? What about four arrays? We consider this two. Now, this example is going
to get way too crazy. That's minimize it down. Now this will look like this. How about a three array? Well, yeah, very simple. Let's take each one of these and replace each number
with an extra set. Now, if we hover over here, wrong number of indices
expected three, let's enter a third one. Now you can see the
coordinate system is in three dimensions. If I run the program now the first number in the
array is one, which it is. This is the very first item. So you can see this is kind
of the concept of two arrays. Three arrays. And you know, it can go on from there. And you may ask the
question, well, how many dimensions
can we go to? Well, the answer 32, if
you're ever wondering. So we can have up to 32
dimensions in an array in shop.
36. 8-3. EXERCISE - Chess - Find the Queen Game: I'm going to do a bit
of a challenge now. I'm going to test
your knowledge on two dimensional arrays
and also problem solving. Consider this template here, It emulates a chess board. If you're familiar with chess, then maybe you've already
figured that out already. If you don't, don't
worry about it. We're going to create a piece of software to find
all of the queens, which is represented by
a Q on this chessboard. Now, this is what the
chessboard looks like. We have a castle, a rook, a bishop queen, and a
king, all the pawns, some empty squares
represented by zero, and the other players
pieces as well. If you're not
familiar with chess, what we want to do
is find the cue. This is a character array
represented by Shah. In a character, they all go in single quotes and you can
only have one letter inside, otherwise it throws an error. What we want to do
is find the cues in this two dimensional array and then output
them to the window. So how do we do this? How
do we find something? Here's our two D array. How do we pick out these queens? Well, what we want to do,
we want to test each one. Is this a cue, Is this a que, no, etcetera, et cetera. In your head, you
should be thinking, okay, a loop. We need a loop. But because there's more
than one dimension, we need to check going across. We also need to check, go down, we check all of these. Go down one, check
all of these down. One, check, all of these. In your head, you should
be thinking, okay, we need a loop and
we need two of them. We already know how many
iterations we need, because we have eight going
across and eight going down. You should think,
okay, 24 loops. Four, because we
know the number of iterations and a loop, because we have to check
something over and over, Let's do 24 loops. The first loop I'm going
to do is the y loop, and that will move downwards.
Let's start with that. We're going to start with zero, because all indexes
start at zero. This is slight 00
there, y is less. Now we want to get the length
of this dimension here. How do we do that?
We take the name of our two array here, period. And then we want to use
the get length method. When we open
parentheses on that, it asks me for a
dimension, well, this is the first dimension, I'm going to put zero in here. That gets the first
dimension and then semicolon and
increase by one each time. That's our first loop. Now we're looping down. We also need to loop across. We're going to need
another loop inside our loop that will
represent the x axis here. We want to get the second
dimension in there, which is represented by one. Now this is going across the
first dimension down here. This is going across the
second dimension across here. Now we have our
two loops set up. We need to actually check
each one of these values. We can do that using
an if statement. That we can say
the current value if is a queen. And then I'm just going to say queen
found at this location. Just so this makes sense. If the item at X, which is represented
by this four loop, and X obviously
gets incremented by one each time that goes across, that goes in the
first slot here. Then the second one is the
Y and that moves down. What we're doing, we're
checking each value, we're going all the way across
and then down one across, down another one across. That's what the loop is doing. And each time we're checking to see if the slot is a queen. If it is, the condition is true, then we're running this
line of code right here that's just saying
queen found at location. And we're outputting X and Y. Let's see if this works. Let's run the application. Queen found at location 03 and Queen found
at location 73. If we're right,
03, this is zero. This is all of zero right here. 0123. That's correct. The next one I believe was 701-23-4567 and then 170123. You can see it
successfully found both queens on this chessboard. If you want to modify that, we can find the kings, and then we can just
find a K instead, and that will find the
kings on the board. That was a pretty fun challenge. If any of this is confusing,
go over it again. You may not get it the first time, don't worry about that. But you will slowly
understand it the more you can watch this video and
understand the problem. But that's kind of like
a real world example where we simulate a chess board, for example, when working
with two D arrays in C Sharp.
37. 8-4. Lists: Now I'm going to introduce a new collection in C Sharp
and that's called a list. Now a list is quite
powerful internally, it's actually built
upon a standard array, but it includes a lot
more options and a lot of ways you can actually work with the information
inside of the array. For example, let's talk about
this example right here. We're defining an integer
array in C Sharp. We're just giving it some
random number values. We're using a four each
loop to go through each item in the collection and outputting it to the screen. If I run the application now you can see all those
numbers right there. Very simple, what I'm going
to do is create a new list. I'm going to mimic
this functionality. You can see the
difference between an array and a
list, for example. Now it's a bit of a
complicated subject. Given our learning so far, I'm not going to
explain everything, but I will cover some of the
things to do with lists. Now, how do we create a list? Well, the data type is list. Now there's a new notation we haven't really talked about. This is called generics. Now, I'm not going to talk
about too much about generics because I think it's quite a complicated
subject at the moment. But what I want to do is define a list which contains integers, for example, you can see Visual Studio is trying
to help me out here. It's actually hinting what
I want to do. It's correct. Let's just press tab
on the keyboard there. And it's written in this
notation out for us. I'm just going to
complete this as. So we've mimicked the
functionality above. Now this line right here is exactly the same as
this line right here. This is a type of collection. This is a type of collection. It's an integer array. Here, it's an integer list, and they all contain
the same information. I'll prove that to you. If I loop through
this list right here and output all the
numbers to the screen, it does exactly the same thing. How do we define and
initialize a list in C Sharp? Well, we use the list
keyword with a capital L in these angular brackets. Right here, we put the data type we want to store in the list. Similarly, if we wanted a list of strings,
we would do that. For example, we put the data type in these
angular brackets, give it a name, and then
we use an equal sign. And then we want to
tell the system, Okay, now we want to
initialize the list. Now we want to create the list and put some
information in there. We use this new keyword, repeat the data type again. Then in these parenthesis, we can either leave them blank or we can give it a capacity
just like an array. We can even pass an
existing collection into it, for example. What I could do is do this. This will create a list based
on my array right here. You can see how it's already starting to be quite powerful. Again, I can prove that
also works by running the application and it's cycling through the numbers that
we've passed into it. You can see it's quite
powerful in that respect. But the thing about
standard arrays in C Sharp for example, let's just work with our
standard array right here. If I look at the native
methods to do with an array, we can't really do much with it. We have some various
methods we can use, like get the length of the arrays or the number
of items in the array, but not really too much else
to do with native methods. What if we want to
sort this information? Maybe put the smallest number at the start and then the
biggest one at the end? How do we reverse the
order of these numbers? Various things like that. Well, this is one of
the many benefits of using lists in shop. What we can do. Let's look at a few examples of
working with lists. Here I'm defining a new list. I can define a new list
and just leave it empty. And then later on
in the application, when we figure out what we want to actually put into our list, we can dynamically, on the fly, add items to it. So I could add this
number right here. And then another one. Maybe if we want to
build an application where we collect
numbers from a user, we can define the list. And then later on we can add in the user's numbers when
we run the software. Now we can see that
the list now contains those two numbers that we've added to it using
the add method here. But not only can we add things, we can remove things as well. We can do various
things natively. But one of the more
powerful ones, we can actually sort the data. We can sort it in order. We can even reverse the numbers. For example, there's define a list with these
numbers right here. And we'll use the sort method. And what this will do,
this will take all of the integers and
sort them in order. That is the only thing you
need to do in order to do that if we run the software. Now you can see all of our numbers are in
sequential order. That's very easy to do, only just this very short
one line piece of code. Here you can do various
things with the list class and it offers a
more powerful way of working with your data. That's not to say necessarily
a raiser useless. You can accomplish these
things with a raise using extensions like link
and things like that, but I won't get into that now. I don't want to complicate
this tutorial too much, but I'm just presenting
some of the advantages of using lists when
programming in C sharp. To summarize, if you have
a collection of data, whether it's integers, strings, or another data type, and you don't necessarily
know the capacity, perhaps you might want to add values during
the application. Maybe the user needs
to add items or you want to control the
data in a better way. Then maybe list is
something for you. Maybe it's a data type
you want to explore. But it is a powerful data type, and I do recommend you use lists with your
adventures in C shop.
38. 9-1. O-O, Classes and Objects: Classes and objects in C Sharp. What is a class?
What is an object? What does all this mean? Well, let me explain Now, Classes and objects in C Sharp, they support what's called the programming paradigm.
What does all that mean? Programming is short
for what's called object orientated programming
and it's a paradigm. A paradigm is just
a fancy word of saying a way of doing
something like a method. If you carry on with your
endeavors in programming, you may see this word a lot, so I thought I
would bring it up. Now a paradigm is a
style of programming. Imagine a chef in the kitchen
with some raw chicken. He could roast the chicken. He could boil the chicken, he could fry the chicken. But each one of
those is a paradigm, a different way of getting
to the end result. So that's what a paradigm is. Now, when dealing with
basic programs like building a calculator or
something very simple like that, paradigms aren't really
important for beginners. It's no surprise, you've
probably never really used any before when software
only has 2030, 40, maybe even 50 lines of code. The way of structuring your
software is not really that important because it's
quite small programming, the programming style
is very important. When you have large
pieces of software, you might have 2030, 100 people working on
one piece of software. Code organization
is very important. So consider this for example. If you have lots of lines of
code that looks like this, how do you even maintain this? It could be 50 pages
long, 1,000 pages long. We need a structure, we need some organization. And that's one of the many
elements of 00 programming. Now, 00 programming,
it's a very large, complicated subject
that has lots of advantages and
lots of benefits, but that is one of them. Now o programming, it dates
back to the 1950s, 1960s, but it definitely
gained popularity as far as I remember
in the early 2000. That's when it
really kicked off. What we've really
been doing so far is what's called
procedural programming, where the program starts and we kind of execute
each line in order. We might have a method or two. And, you know, things
are very simple. But again, in very large
software applications, this is quite hard to maintain. For example, 00 programming, very big, very
complicated subject. I can bore you with the whole ins and outs
of it right now, but I don't think
that's a good way of learning 00 programming. I think the best way of
learning is to deal with some real world
examples and actually go through it with
working examples. So do you remember
the movie Karate Kid, Where Daniel Larusso
is painting the house and painting the fence
and sanding the floor? And secretly, he was
learning all of this karate, but not really knowing why. And then at the
end, Mr. Magi said, oh, okay, now test your skills. So, for the benefits
of staying engaged, that's exactly how I want
to teach O programming, and I think that is
a fantastic way of learning 00 programming
by learning by example, then coming back in a roundabout
loop right at the end. So when I talk about complicated words
like instantiation, polymorphism abstraction,
cohesion, coupling, all these complicated things
I could discuss right now. But the problem is in reality, they're
motivation killers. And for the interests
of preserving motivation and
keeping you engaged, I'm going to do
this this way and I think that will be
a fantastic way of learning this classes
and objects in C Sharp. What is a class?
What is an object, and how does it benefit me, and why should I even use them? So far, if you've
been following some of the tutorials
we've made so far, we've created some
basic examples like multiply two
numbers together. Where we take two numbers from a user and we multiply them
together, for example. And when we take a
number from a user, we can represent this as an integer data type,
which is quite easy. And that's all we need to do. We don't need to know
any more information about these numbers to
multiply them together. Similarly, if we take
the name from the user, we can store this in a simple data type which is a string, and we just store
the user's name. So very easy. But how do we represent a
complex data type, like a user or maybe an
account like a social account, or a bank account, or even a bicycle like
a real world object, or a sandwich, Or even a whole planet like planet Earth or
something like that. Well, so far with our cano
procedural programming style, maybe to represent a user, we might have a string that might be the
user's first name, and then another string
for their last name. Maybe an integer for their age, and then maybe a string
for their username. If they have a user name, we could have maybe a decimal or a double
for their height. The list goes on.
There's so many things you can store about a user. You can see I already have five lines of code for
all these variables. This can page right here, is going to fill it very fast
with lots of information. Perhaps I could use these
five data types here. These simple data
types, string, int, and double to represent a
complex object like a user. Similarly, if I have a bicycle, I might want the
color of the bicycle, the brand of the bicycle, maybe the measurements,
things like that. And that's how I would
represent a bicycle object. But how do I put all of
these into its own object? For example, rather than for every user in
our application, I can just type user and we
could have our own data type, like a user data type. That'd be pretty
cool, wouldn't it? This is one of the benefits of using classes and
objects in C Sharp. Let's have a look
how we can actually create our own data
type in C Sharp. What I'm going to do now is
create a brand new class, basically a brand
new custom data type that we can use anywhere
in our software. If we go over to the
right hand side here, this is the name of our project
right here, programming. And it has a little C sharp
icon with a square around it. So I'm going to
right click this. I'm going to go to Add, and then I'm going
to go to class. Once we're here, we can
see classes been selected. Down here, we can give
the class a name. Now you can call the class
whatever you would like. But it's common practice
to start it with a capital letter to
do with its purpose. What is the purpose of this
class? What does it do? What information does it hold? Or what is its primary function? That way, when you have
a very large application with maybe 1,000 classes, you know exactly from the name, what it achieves,
what it aims to do. What I'm going to do is create a custom data type called User. That is going to do is
store information about a potential user who might
be using our software. I'm going to call it user, then I click the ad
button right here. What that does, it creates a brand new class
in our project. This is our project here. We've been so far, if you've been watching our
previous tutorials with the default class which
is called program, and we've been working
with the main method. You can see here there's a class called program and the main method sits inside it. This is a default class of
a console application type. But if we go over here, now we have a brand
new class called User. And now we can put
some information inside this class right here. So you can see Visual Studio is hinting on what I might
want to put in here. Yes, it may be a preferable
way of doing this, but I'm going to talk about get and set in a future tutorial. So I'm going to do this
slightly differently. What we want to do
here in our new class, which is called user, is to put everything
about our user. So maybe the user's first name, the user's last name,
the user's age. Anything to do with a user. What I'm going to do,
I'm going to define some simple variables in here. So what I'm going to do, I'm going to call it maybe
first name for example, and then maybe a last name, and then maybe the age,
something like that. Before each of
these, I just want to put this internal keyword. Don't worry about what
that means right now. We're going to cover that
again in a later tutorial. But what I've done, I've defined three simple data types here, two strings and an integer. And all three of these are
inside the user class. This is the new class we've just created. What does
all this mean? This is our custom
data type right here, Just like an integer
is a data type, a string is a data type. Now, user is our own
custom data type and it has all of these
things inside it. Let's look an example
of what this means. If we go back to our main class here with the main method, we can actually set up what's called an instance
of our new class. Just like when we
create a string, we might do something like this. But when we have a
custom data type, like a new class, for example, the format is a
little bit different. It would be our
custom data type, which is the name of our class, which is user, because we've created a class
with the name user. You can see now
this is green and it actually has some
information about our class. If I type in Bacon for example, then you can see it's
black, there's a red line. That's because we don't
have a class called Bacon. Now we have a class
called User, It's green. And we can actually
make use of this. Now we're going to give it a
name just like we do here, for example, with
a simple variable. I'm just going to call it US. R, short for user. Then I'm going to go equal. And visual studio is giving me a hint on
what I want to do. That is exactly
what I want to do. I want to create a new instance
of our class called user. And I'm giving it the name USR. I can give it whatever name I want, it doesn't
really matter. Now I have a brand new variable, just like a variable
here of type string. I now have a new variable
here called US user. If I start using my variable USR and
put a dart afterwards, you can see I can
actually access these variables I've just
created inside our class. You can see here, last name, first name, and age. Let's set up a sample
user variable. If I say user first name, we know this is a string. Let's call him, I don't know. Let's call him Bob. Why not? Let's set up a last
name for our user. We'll call him Bob Smith. Then lastly, Bob Visual
Studio wants me to put 30. Why not? I'm not sure why Visual Studio is indicating
30, but there you go. Now what I've done
here, I've created a brand new user
object right here. And then I've given
it some information. These fields here. These are the exact same
fields we've defined in our brand new user which
is like our data type, and we've given it
some values here. What I can now do is actually
use this information. If I do console right line, I can actually output some of this information
to the screen. Let's say, let me output
the user's first name, last name, and age. Let's keep the console window open so it doesn't close on us. Now let's run the application
to see what we have here. Running the application, we can see we're actually outputting all of the values for our
custom data type to the screen. We're setting the
values this way. We're outputting the values
of our custom data type, like so to the screen. When creating
classes in C Sharp, such as our custom
user class right here, imagine this class being a
blueprint, a specification. Everything inside our class
here is to do with a user, it's not to do with a bicycle or a sandwich or
something random. Everything in here is involved
with creating a new user. We have the name of the user, the age of the user, everything to do with a user. Imagine this being like
a blueprint for that, or like I say, a specification. The process here, what
we're doing is creating an object just like
when we create a simple string variable
called name, for example. When dealing with custom
classes and things like that, these are called objects. Now you can see where
the term object orientated programming
came from. Because we represent real
world things like users, cars, bicycles as objects
like classes, USR. Here is the object, this is the data type
which is a class. This process here is
called instantiation. And it's called
instantiation because you're creating a new
instance of a class. What we can also do is create a second instance
of the same class. This is the first instance. This is the second instance. We can create 50. We could create 100 for example. What we can do here
is another user and maybe he's called Darren
Smith and he's 75 years old. Similarly, we can output his
information to the window. As you can see there, you start to see the true power of object oriented programming. We could create thousands
of these user objects and replicate thousands of users in our software
if we would like. We're not limited to only
having user objects. We could have account objects, lots of different things to
bring our software together. What we can do with
these objects here, we can pass them to methods, we can put them in arrays, we can cycle through
them in loops. The limits are endless. But that is only a small sample of object orientated
programming. And it starts with creating
classes and new objects. So I hope this helped
you get started with your object orientated
journey in C shop.
39. 9-2. Constructors: I'm going to talk about
constructors now in C Sharp. What is a constructor?
How do they work? Well, let's check it out here we have a
very simple example. We have a custom
class called user. We have three variables
inside the class, which is information about the user and the
age of the user. Then we're just setting
up a new object, which is an instance
of the class. We're giving it some
values, first name, last name, and age, and
outputting it to the screen. Very simple piece of software. I'm going to introduce a
constructor into this example. Now what a constructor does, it helps us construct
our objects. Here we're creating a new
instance of our class. Here is our object. What a constructor does, it gives us some help with
setting up this object. Let's learn by example. I think that would
be easier here. Here we're setting up
a new user object. I'm just going to copy
and paste this one. And we're going to create a
new object, another object. Okay, here I'm creating
a new user called Tony, Tony Smith and his age is 41. When I set up this user, you can see it uses
four lines of code. Maybe if we want to
set up 100 of these, it's not going to
look very elegant, it's going to look
quite bloated. This is one of the advantages
of using constructors. What I can do when I create a
new instance of this class, I can actually pass these
values as parameters. When creating a new instance, what I can do is
pass in say Tony, I can pass in Smith and then
pass in the age right here. Then I can delete all
of these lines of code. And then essentially this line will do exactly the same thing, these four lines here. That's one advantage of constructors is code
minimalization. It's represented
only on one line. But how do we set this up? Because right now
we have a red line. And if I hover over that, it says user does not contain a constructor that
takes three arguments. Well, let's go and add one. I'll go into the
user class here, I need to set up a constructor. How do I do that? It starts
with the internal keyword. Now, don't worry about what
internal is right now. I'll discuss that in
a later tutorial. All constructors take
the name of the class. The name of the class is user. I'm going to put the
name of the class there. After that, I put parentheses and then the
familiar curly braces. This is a basic constructor
in its minimal form. We can have more
than one constructor per class if we want. What I want to do is
take in these values here and initialize them
into our variables here. I want to put those
values right here. What I need to do, when
we worked with methods, it works very similar to that. I want to pass them
as essentially parameters I'm
going to do first. For example, first
name, last name, age. When you give your
parameters name, give them meaningful names such as first name,
last name, and age. And make sure they're
not exactly the same as these local
variables right here. Give them a slightly
different casing, for example, or a
different name completely. I'll discuss that
in a later tutorial when I talk about this keyword. For now, our parameters are coming into our
constructor here. Now I want to initialize these local variables with
these values right here. It's very easy to do that. I take the local variable here, I set it as the value
of the parameter. That's one done already and we'll carry on
for the other two. Visual studio has
helped us there nicely. Let's just review what
is going on here now. The red line has gone away. If I hover over this, it's working.
There's no red line. I'm passing in a string, a string and an integer into the constructor for the class. When creating our object, these values get passed in as parameters into the constructor,
which is all of this. Then the value of the
parameters assigned, well, initialized into
our local variables here. Now, these local variables
here will forever hold these values as long as this instance remains
alive in our system. That's pretty cool, isn't it? Let me just run the software real quick so you can
see what's going on. I'm going to comment this out, and I'll come back
to that in a second. Now, let's just put that
there, no problems. We run the software. Right now, you can see it
says Tony Smith, age 41. It looks like it's
working correctly. Let me just undo those comments and talk about one more thing. You can see something
interesting. Now, there's a red line
underneath this part right here. When we try to set
up a new object, it's no longer
working. Why is that? That's because in our
class here, by default, we have no constructor.
It looks like this. However, once we define a constructor with
parameters like this one, we can no longer set up an instance of our
class like this. There's an easy way
to get around that. We define just a very
basic constructor with no parameters. So now you can see this red line is gone
and everything's happy. How is that working? Well, when we call
this constructor here, when we create this object, we're passing in
three parameters. When this line is
executed by the software, the code execution
jumps into here. And everything is set up here. When we create a new instance
using this line right here, there's no parameters, this
constructor is called. Instead, this is never run, only this section here, There's nothing going on here. Now that's the difference
between the two. There's actually two constructors
now inside this class. This is using the
first constructor, this is using the second. And we can have 50
constructors if we want to, but that's kind of
how things are going on internally inside our class. So you can see constructors have allowed us
to minimize code, you know, on only one
line, for example. But what else can
they do? You know, what's another benefit? Well, constructors like us
say can help you construct your object and it kind of
does it behind the scenes. So from this file right here, we don't really need to know
how this user is set up. We're just kind of passing it some information and we can kind of get it
back when we want it. So all of that kind of logic is hidden away from us,
which is pretty cool. Constructors can internally do some stuff we don't need to worry about behind the scenes. For example, if I call this constructor by passing
in the two names in the age, I could output something to
the window, for example. I could tell the user, we're setting up a new user. For example, when I
run the software. Now you can see I get a
little message saying, okay, please wait, I'm just
setting up a new user. And then it outputs
the information. Constructors, do
some extra stuff, they don't need to
just set up variables. They could log to a database, they could talk to a website. They could open a
database connection. They can do lots of internal
things behind the scenes. This is how they can help
construct an object, and this is why they're
called constructors. Constructors are pretty
powerful elements of object orientated
programming. And you can see, using this
example in this tutorial, how it simplifies things. Perhaps not in the class itself but definitely working
from out here. You can see how simple
everything looks by just using one line of
code to set up an object. And we don't need to worry about the internal things
going on here. That is an example of
constructors in C shop, and I hope you find
it quite useful.
40. 9-3. Object Methods: Let's talk about object methods. Now, here I have a
sample application. What I'm doing, I'm
creating a new list here. Then I'm creating three users. They all have unique
information here. For example, Tony
Smith is 70 years old, Bob Holmes and Tyrone Jones. Then each of these objects here, I'm adding each one to our list. Now our list of users will contain all three
of these objects. I'm using a four
each loop to cycle through all of the
users and in turn, output all this information
to the console window. Let's just take a look at that. Now you can see this
is the result we get. It's just outputting all of this object information
on the screen. Now what I want to do,
I want to find out which of these
users have retired. Have they reached retirement
age or are they a pensioner? Depending what country you
live in now In the UK, I'm not sure about America, but the retirement age is, I think 66 for males. We'll just use 66 as an arbitrary number.
It could be anything. Tony Smith would be
retired in that case, but Bob Holmes and Tyrone Jones have a ways to go yet
before they're retired. What I want to do, I want
to output an extra bit of information to say
is the user retired? How we would normally do this is set up maybe an if statement. And we say if the user's age, age is greater or equal to, let's just say 66 is
the retirement age, Then we'd say, okay,
they're retired. We'd say retired. We'll initialize it to false. If they're greater than that, I'll just say retired is true, but for example,
something like that. That's how we would
normally set up a case where if they're retired, we'd use a condition. And then we output that
information to the screen. It would look
something like that. You can see we have our nice
loop here with our age, last name, and age. But when it comes to retired, we have all this information. It looks a little bloated. Maybe we can move
this somewhere else. Maybe inside our class here. And then just have
another one liner here. This is what we can achieve
with object methods. In this case, what we want to
do is put this logic here, this condition inside our class. We don't need to worry about it. We don't know how it's
calculated, we don't really care. We just want a little
variable here, this is retired, and we can
display that information. Let's have a look
how we can create an object method by moving this logic inside of our class. Just before I do that, I'm going to run the application
real quick. Just so we can see
the result here. You can see underneath each user it says
retired is true because this age is over 66 and the rest are false just because
they're not 66 or over. That's going to move
this logic into what's called an object method. And we define that inside our class right here.
Here's our class. Here we have our variables, here we have two constructors. What we want to do is just
create a method in here, we're going to use the
internal keyword again, Don't worry about what
that means right now. We're just going
to put it in here. When we define a method, we need a return type. It's going to be a bull
lien because we want to say are they retired true or are they retired
false, For example. Now the name of the
method I'm going to call it is retired then. It doesn't take any
parameters because we have access to the age through
the class itself up here. Use at age, we're just
going to create our method here and then what we want to do is return
something like this. Now, Visual Studio has already hinted to what
we might want to do, but let's just take this here. What we're saying here
is if the user's age is more or equal to 66
retired equals true, we could also say that, which is the exact same thing, because this condition will
evaluate to true or false. And then the result is stored in a bolen. Very simple, really. What I want to do is
take the condition here, go to our class and we want to return this
out of this method here. Just like that, because
we're inside our class here. We have access to user age here. We're just going to take this and we're going to
put that there. We've created a method, it has no parameters, but it has a return
type of booling. We're returning true or false if the user's age right here is
more than or equal to 66. Coming back here, we can
remove this completely. Now what we can do is
take our object here, which is user, because we're going through
this on a fore loop. And then we can access a
brand new method that we've just created right here
called is retired. And you can see that
returns a bolen. So I double click that
open and close parentheses because it takes no parameters. And now you can see the code looks a lot more streamlined. We don't have that kind
of condition in here. We just have four kind
of nice bits of code. One getting the name, one getting the age, and one
getting if they're retired. I just realized I
spelt retired wrong in the method there,
nobody's perfect. But you can see it looks
a lot more simple now. But one of the benefits and
advantages of 00 anyway, is that your logic is kind
of hidden away in here. Say for example, if one
member of your team, if you're working on a big team, works on this class here and
you work on this class here. You don't need to worry about how is retired is calculated. You don't know, maybe
you don't even care. You don't even know what
the retirement age is. That's okay, because
the only thing we need to call is this
method right here. Then maybe our friend on our
software team can, you know, deal with the intricacies of working out maybe what
the retirement age is. So the principle is it's kind of hiding the
information from you, it's abstracting it away. And that is one of
the key points of object oriented
programming abstraction. You don't need to
know how this works. For example, if you
own a coffee maker, you don't need to
know how it's going. You know how it works inside, internally, all the electronics. The only thing you
need to do is fill it up with water and
press the button. So that's what I'm kind of
trying to explain here. We don't need to
know how this works, we just need to call
the method and it gets as a true or false value. So that's one of the
advantages of using object oriented
programming and this is how object methods
work in Sea Shop.
41. 9-4. Access Modifiers (public, private, etc): Now I'm going to talk about
access modifiers in shop. Sounds a little complicated, but I'm going to break it down. So it's very simple and
you're going to understand everything to do with
access modifiers in shop. So what is an access modifier? Now, before we talked about the kind of job a
class would have, it sort of models a real world
object. In this example. Here I have a video game class. When I create a new
video game, for example, it wants the video game name, its publisher, and a
rating for the game. So you can see a class here represents a video game object. It's like a real world object. And when we create classes, we want everything
inside the class. For example, this
video game class here to just be about
the video game. So we don't want to talk about anything else other
than the video game in here. Maybe like what food we're eating while we
play the video game. Or maybe some information about the user playing the game. Because maybe that
user information could be in a user class. Or maybe the food
the user is eating while playing the video game
would be in a food class. This is quite important
with 00 programming, you keep the classes what
is called highly cohesive. And that just means
everything inside the video game class is directly
to do with a video game. That's the general principle. Anyway, this not only
benefits code organization, but it allows different people
to work on this project. For example, maybe 100 people. So you can delegate
one or two people to work on, say, this class. While another person
might focus on this main class right here, it has multiple benefits. But how does that tie into access modifiers and
things like that? Well, consider
this example here. What I'm doing, I'm constructing four video game objects here. I'm putting in some sample data, what is happening
behind the scenes here when I'm constructing
these four objects? I'm just setting up
some variables here. The name, the publisher,
and the rating. You can see the parameters are coming into the constructor, and I'm just setting the values. However, secretly
inside this class, what I'm doing is generating a new unique ID for each
object we're creating. What's happening here is
I have a method here. It's just setting this variable
up here to a unique ID. You don't need to
worry about what this does, but what it does, it generates a unique ID, which is unique and there
should never be a duplicate. This is an inbuilt function you can use in order to do that. And it's just setting this
variable here to a unique ID. So if we create a game here
using this constructor, it will always have a unique ID. From this part of
the program here, we have no idea
this is happening. We're just passing
in three values. We didn't even know
it had a unique ID. We have no idea what's
going on behind the scenes. And that's the beauty of
object oriented programming. We don't need to know and
we don't need to care. For example, I've just created this object here
called Game One. When I go in here I can
re edit the publisher. I can change it to
a different value. Now I've constructed it. Let's say for example, World of Warcraft Blizzard have been taken
over by riot games. Then I might want to modify the publisher to riot games later in the software,
for example. I can do that no problem. However, what if someone can accidentally change
this ID value here? What I'm going to
do is go out here, game one, and you can
see this ID field here. I could change this
to whatever I like. The thing is I don't want
anyone to change this ID field. It's already unique. I don't want any other team
member modifying this value. It could corrupt the data
because the ID is unique. And anyone could just change this ID value to ham
sandwich, for example. You know, that could have
lots of adverse effects. One, it could break
the software. Two, it could cause, you know, information loss. You know, it could have many
bad effects to the software. So what I want to
do, I want to keep this ID private to the class. I only want the class
itself to know about this ID and manage the ID
internally to this class. I don't want anyone else
in the software modifying any other classes or any other parts of the
software to touch this ID. Maybe they can just
like look at it, but I don't want them to
edit it, for example. This is where access
modifiers come in handy. Now access modifiers enforce
what's called encapsulation, is to make sure sensitive
data like ID in this case, is hidden away from
users or people, or even other pieces of software that should
never have access to it. That is an example of encapsulation
and why encapsulation is important when generating
object oriented programs. Let's take a look how we
can restrict access to certain variables or even
methods using access modifiers. Let's go into our class. Let's talk about various
access modifiers we can have in C Sharp. Now, the first one is
what's called public. You can see here public. That just means anything
defined as public, you could have a
variable for instance, or you can even have a method. For example, this one down here, if I make this public. And that means when we create
an object of this class, we can access it from
outside of the class. We can access it from
anywhere in our project. Anywhere in our solution. I've typed in game one, then a little t there, and now we can access ID. We can access the generate
new ID method here. That's because these
are public and we can access them
from anywhere. Now the other one is
what's called internal. We can have variables here, we can have internal
constructors, we can have internal methods. The difference between public
and internal is internal is only accessible within the current assembly or project. What does that mean?
Well, come across here. So far, we've been working
with one project so far. Now what we can do, we can have another project in our solution. We could have 50
projects, for example. What that means in our project. Here, our default project, only the classes inside the project can access
internal things. If we're in another project, maybe this project
represents the database, like the data layer or
maybe the front end where all the maybe
graphical things are. Then they can't access
internal things because it's only internal
to the current project. We'll be talking more about
multiple projects later, but that's basically what
the internal keyword is. Another access modifier is
what's called protected. Now, we'll be talking
about protected later on, so don't worry about
that one for now. The last one I want to
talk about is private. Now, private is very important for the
example I've just given with regards to accessing the ID from outside
of this class. What private does it enforces? Local variables like this
one or even methods like this one only be accessible from with
inside the current class. What I've done, I've
changed this ID to private and I've changed
this method to also private. If I go back to my main program here and put a dot
after this object, you can see that
the ID property, the ID variable, is
missing from this list. You'll also notice that
the method to generate a new ID is also
missing from this list. You can see what
is happening here. It's enforcing encapsulation. It's hiding sensitive
information because we only want the
video game class to be able to generate new ID's and you control the ID
for the video game. Nobody else in this whole piece of software needs
to know about ID's. It's unique to video game and it should stay unique
to the video game. Therefore, these fields should
be made private because only video game needs to know about this, it's
private information. So consider it like
that for example. However, name is
publisher is public. Let's make rating internal. As long as I'm working
inside the same project, I should be able to access
name, publisher and rating. Which I can do right here, Name rating and publisher. Right now ID is private. If I trying to use that anyway, for example, put some
information inside ID there. You can see I have
an error here. And if I hover over that, it says video game dot ID is inaccessible due to
its protection level. That's because it's private. We can't actually access this information if we try and run the software
and compile it, it's not even going to letters. So you can see this is
how strict it's enforced. As soon as I change this
ID to public or internal, then the red line is
going to go away. The protection has disappeared. We can run the
program as normal. So this is the power of
access modifiers in C Sharp. It enforces what's called
encapsulation and it protects our sensitive data from either
other pieces of software, other segments of the
existing software, and even users working on different parts of
the software as well. It enforces data integrity and prevents a lot of adverse issues that can happen because of this. These are access modifiers
in C Sharp and why they're very useful when
creating classes and objects. Lastly, I want to talk about what can have access modifiers. Here we have a method that
has an access modifier. We have a couple of
constructors here that have access modifiers and also
some local variables up here. They also have access
modifiers here. But you'll notice that the
class that contains all of these elements also
has an access modifier. Now public is the
weakest access modifier. If something is made public, then anyone anywhere in the whole solution
can access this item. However, the class itself
is marked as internal. And that means only
classes inside the existing project or
assembly can access this class. By default, this
stronger access modifier overrides anything
weaker internal. We'll override all these
public access modifiers here. And that is because
the surrounding class is marked as internal. By default, the access for
these will all be internal. If they're public, it will
look something like that. Even if they're
marked as public, this is how they
will be accessed. However, if I mark
the class as public, then it's no problem
because this is the weakest access modifier. These will all be
public if you've ever worked with file and
folder permissions for operating systems
and various settings can override the subfolders, It works very similarly to that. To clarify, if I was able to
mark this class as private, then by default everything
inside it will be private regardless of
the access modifier. That's the point I'm
trying to get across. Now, writing access modifiers
in C sharp is optional. If I remove the access
modifier from the class, then by default classes
are all internal. I could write this
and this would be exactly the same
as doing this. It's optional, but it's
assumed internal by default. However, anything
inside the class, methods, constructors,
properties, or variables, by default these
are all private, unless explicitly marked
as public or internal, Then it's assumed
they're private. Writing this would be exactly
the same as writing this. In this case,
private is optional. We could remove the
private access modifier from the method and
the variable up here. And it will have
exactly the same effect because by default, anything inside the
class is assumed private if there's
no access modifier.
42. 9-5. Properties: I'm going to be talking
about properties in shop. Now, we're also going to be discussing the get keyword
and the set keyword, also known as
getters and setters. So what does all that mean? Well, let's take a look. If you followed along with
the other tutorials so far to do with object
oriented programming, then this is going to make perfect sense and
lead on from that. If you haven't, then I
highly recommend you watch those so you're
about to understand what I'm going to show you. What is a shop property? Why should we use them? So shop properties force one of the core principles of 00 programming, which
is encapsulation. And that's just ensuring sensitive information is not accessible from anywhere else. Like when we talked about
this private variable here, it's only accessible
inside the class and then nobody accessing it has any control over
that, for example. So this is going to push
that one step further. So I'm going to
present a scenario here and show you
one of the benefits of using a sharp properties and getters, and setters here. In this example, we've defined
a video game class here. It has various variables
here we can use and a constructor with
three parameters. Here we're setting up
four video game objects. Game 123.4 Inside
the constructor we're creating a video game
name, the game's publisher, and a rating for the game, let's say when our
program starts, all of this data is
loaded into the system. At some point later in the software the user
wants to modify. For example, the name of
this game right here. They've clicked the edit button, perhaps in the guy, and they want to
change the name. For whatever reason, maybe the video game is now
called a different name. We're going to ask the user for a new name for this
game here, Game One. And they're going to type
something into the system. Let's say for example, we ask them for a new name, we can set that using
the variable name here. Maybe they accidentally hit G on the keyboard,
then hit Enter. What we're doing here,
we're just passing in their input into this
variable. No problem at all. We'll go on with our day. However, maybe this
is not a good idea. Maybe we want to validate
this input first. Maybe we want to make sure that the game name has at
least two characters or doesn't contain any numerical characters
or something like that. Maybe there's some
checking we need to do. This is where C sharp
properties can come in. In this particular scenario, there's lots of reasons for
using C sharp properties, but this is just one example
we're going to go through. Now what I could
do in this case is that instead of setting the
name variable directly, I can create a method
here called update name. And that can take in our
new name from the user. What it can do, it can do
various validation checks. It can say, okay, is the new name less or
equal to one character? If so, then we can't update the name and we can do any
other validation on the name. And then finally, we can
actually update the name. For example, what I
can do here is say, game one to update name. Now, rather than
setting a variable, I can use a method. In order to achieve
this, I pass in our potential new name
which the user gives us. Then this method
will either return true if it can or
false if it can't. And then update the internal in a name variable here
internally within the class. And that's perfectly acceptable rather than using a
method in this case, because what could
happen is maybe we need a method to then
update the publisher, or we need then another
method to update the rating. But now we're using methods to update the name, for example. Well, we can still
access the name itself, so we need to restrict access
to the name because we only want to update the name field using our
new method, update name. So this is essentially where
C sharp properties come in. And the principle of making local variables to a
class private only, you can see in our class here we have all these
variables right here we have three public
ones and one private one. We've gone through one example and I'm going to
tell you now it's common practice to make all of your variables inside
classes private. That means no one
outside of the class can modify these variables
in any way at all. If I access the game one object. Now I can't access
name directly. I can't access the publisher
variable, nothing. The only way I can access or update the name is using
our update method. And that's exactly what we want because when the user
types in some input here, we want it to go
through the validation. We want to make
sure the name has at least this many letters or, you know, various other things. And then we want to
finally update it. So this method here is an acceptable solution
on how to do that. And it enforces that all our variables here are private because
they're sensitive. We don't want other
people, you know, accessing these and putting
any old values in and it enforces encapsulation as
well a Core 00 principle. But what if I told you there's an easier way of
doing this method? We don't have to write
a method like this for every single time
we update a variable. Maybe there's another way. This is where C sharp
properties come in. So I'm going to create
a new C Sharp property. Now when we create a property, we give it an access modifier. I'm going to call it
public because I want everyone to access
our name field. Then the name is a string. As you can see here,
name is a string, then I have to give it a name. Now, when creating
properties and variables, for example, these are
also known as fields. The fields themselves usually and typically are
all lower case. You can see all of these
are case right here. The properties themselves, they just have an upper
case first letter. If the variables
here have two words, then it would look
something like that. Title case, for example, without the white spaces. That's common practice. The local fields here, the local variables
lower case and the properties are always
capitalized at the start. That's just good practice. Once we've done this, I'm going to show you a
C sharp property in its basic form now. Anytime we want to update
the private field name, we go through this
property here, just like when I talked
about the example. Anytime we want to
update the name field, we use this method. Well, rather than using
this method here, we're going to use this C
sharp property instead. Anytime we want to access
this local variable here, we're always going to use
our property instead. Consider this as an accessor
for our local variable here. In order to get the variable actually get the value of it, it's going to return it
using the return keyword. Anytime we want to set a value, then the local
variable is going to equal this special keyword
here called value. That's the value being
passed into this. Let's look at an example
of that right now. If we go into our
main class here, rather than using this
method here in our example, what I want to do is
say game one name. This is our shop
property right here. Then we can actually give this
a value like for example. Now what is happening here, we're using the property name, but internally
inside this class, it's actually going in here
and setting the value. This section right here
inside this Get statement. This is where we want
to do this validation. Let's copy all of
this right here, then let's put these curly
braces on a new line. Let's delete that for now. What we're doing here is anytime we set this shot property, this set statement is called. You can see here when we use an equals sign with a new
value on this shop property, internally this set block, all of this is executed
at the end of this, we just want to set our
local variable here, name, to whatever
value is passed in. That magical keyword
value I was just talking about will equal
this value right here, Whatever is being assigned. Any time this
property here is set, which is what we're doing,
we're setting it to, then we're doing all
this validation here. We have to use the
magical keyword value, which is the value we're
actually checking. This would accomplish exactly the same as this method here. Value just replaces the
name in this instance, let's just check this out and run through
it one more time. We're giving the shop property
name a value right here. Now, value is going to equal to, it, could be whatever. It
doesn't really matter. Then the flow of
execution comes in here, and this set method is called because we're
setting a value, this magical keyword here. Value is going to equal because that's the
value being passed in. Now we're checking
that the user's, the length of the name is
less than or equal to one. If it is, well we
can't update it, then tough luck, We do any other validation,
whatever it may be. If we can finally update it, then we're going to set
our private variable name, which is this to the value
which is being passed in. That is the magic of using a shop property and
the set keyword here, we don't need a
whole new method. In order to accomplish this, we can use inbuilt
functionality. The main takeaway
from this is that shop properties control access
to sensitive information. And these items are all our local fields here are all considered
sensitive information. We don't want users just
putting any old values in here. We perhaps want some
validation to make sure, you know, that the values
being passed in are accurate. You know they're valid or
for whatever other reason. And then when they finally are, then we can update our sensitive and precious private variables in this case. So this is the advantage of
using C sharp properties. We've talked about the set
keyword quite extensively. Let's just cover the
get keyword real quick. The get keyword
just actually gets the value of our
private variable. Again, we can do various things along the way before we
ultimately return it. We can do anything we want here, just like in the set
keyword right here, We can do anything we want. But ultimately, we're finally going to return it out of here. What we can do here,
let's output the name of the game here to
the console window. When this line executes here, we're just output in game
one name to the window. So you can see right here. So what happens is internally when we
actually get this value, so what we want to do is
get the name of the game. Internally this get
block is being called. We can do anything we
want here, any checks, any validation we could log
to a database or a file. And then we can finally return our sensitive information here, the private field out of here, and then out to the window. You can see the get keyword, in this case controls the getting of our
local variable here. Similarly, the set keyword
controls initializing a value to our precious sensitive
local field right here. And again, it's always
good practice to have a C sharp property for every one of your
private fields here. And by default, you should
always make your local fields private unless there's some
extenuating circumstance or special reason not to. One of the other
things we can do with C sharp properties is
to make them read only. What I mean by that
is that the user can access the
private variables, but they can't initialize them, they can't give them any value. For example, let's say
the publisher field, we want to make that read
only. What do I mean by that? For example, say
if I want to get the publisher for any
of these game objects, I would use Game one publisher. And that would be like read only I can access
the information. But when I actually
try and set the data, for example, setting the
name, I can't do that. It won't let me, how do
I go about doing that? Maybe it's a useful thing. What we can do here is create a new property for
our publisher. Again, we have our
familiar format, we do an upper case on the
just for good practice. Then visual studio is helping us by hinting what
we might want to do. That's great, I'll use them. This is how to make a
property read only. We do, we just do not define
a set keyword at all. Only have a get in here. Now, you can't have
a set by itself, you always need a get. But you can have just a get
that makes it read only. Let's have a look
at that example. Now, if we want to display publisher to the screen,
we can just do that. We can display the
publisher to the screen. It's no problem at all,
it's going to work. If I try and actually
set a value in here, I want to update this
publisher to anything really. You can see there's an error
here, there's a red line. If I hover over that,
you can see here, property or indexer
cannot be assigned to, it is read only. That's just because
we haven't actually set a set keyword here. There's no setter, we can't
actually set a value in here. This is quite useful if you have any sensitive fields here where you only want read access. Maybe we want to read
our ID field here, but we don't want the user
to set it for example. Then we would have something like this where we only provide read access to our local
variables right here. One other thing we
can even do is add access modifiers to
our and set keywords. Here we have our name here, we want everyone
to get the name. But however, maybe we want to make the setting
of this private. Only things inside our class
here can actually do this. What we can do here, we can
make the setter private. And that means if we try and set this name value here from
anywhere outside this class, it's not going to letters. So if I go to the
main file here, what I'm doing is
trying to initialize the name as a value.
I hover over that. You can see it cannot be used in this context because the set
accessory is inaccessible. We can't actually set it from anywhere outside that class. As soon as I remove that, you can see the error disappears and we can set the
name once again. Sharp properties are
actually quite powerful, we've only just touched on them, but I think this will
be enough to get you started with your
endeavors in using them. What you should
take away from this is that properties in C Sharp, the control access using getters and setters to
your private fields, which are part of
your C Sharp classes. Thank you for watching.
43. 9-6. Inheritance: Okay, inheritance in C Sharp. You may have heard
the word before, you may not have heard it, but I'm going to explain
it right now. So what is inheritance
in C Sharp? Basically, the core
principle around inheritance is to increase code reusability. And that is very important even in terms of object
orientated programming, not in terms of object
orientated programming. The thing is, if we copy
and duplicate code, then our software will eventually be really
hard to maintain. It's going to have
a large file size and you're going to
have a lot of trouble. Always, always reuse
code where possible. Let's take a look at an example of
inheritance in C Sharp. So what I have here is a
very basic application. I've created a new animal object and I have an animal
class for that. Let's take a look at
the animal class. So here's my animal class. It has two private fields
here, name and age. So the name of the
animal might be Rocky, and Rocky's age might be seven, like Rocky might be
a dog for example. I have two basic
methods here that just echoes the name
of the animal to the console window
and also another method here that echoes
the age of the animal. I have two shop properties here, two public properties that allow control over my private
fields here, name and age. So it's a very simple class. I've created an
animal object here. I've set the name property
and rocky age to seven. Now I'm just using these
methods here that just echo these values to the screen
if we run the application. Now you can see
it's very simple. My name is Rocky, I
am seven years old. So that's a basic
animal class there. So now let's say I want
to expand my application. Maybe I want a piece of software where I can
create a zoo of animals. I might want a dog class, rat class, a cat class,
a hamster class. I might want maybe
20 classes and each one representing an
animal in its own way. If we come over here now, we can right click
the project here and we can go to add new class. And let's say we want
to create a dog class. This class will have
everything to do with a dog. For example, maybe
zoo has hundreds of dogs and we want to manage our dogs in its
very own dog class. It's perfectly reasonable. Again, we might
have a cat class, a hamster class, lots of things. But what we want, our dog class, we want all of
this functionality here of this animal class, because our dog will have a
name, it will have an age. But maybe it has
some other things, like maybe some methods
to do with digging. And not all animals can dig, For example, maybe something
specific to a dog. But we do want this
core functionality. Our dog is going to
have a name and an age. I want all this stuff and I'm going to put
that in my dog class. So now I can kind
of build on this. I can add some methods
for, you know, the dog digging or the
dog begging for treats, or maybe certain dog tricks. But the problem is we've copied all this core functionality which is going to
work, no problem. But the problem is when
I have another class, maybe a cat class or
a guinea pig class, again, I want them to have this core functionality as well. And the problem is I'm going to have all this information in about 20 different classes and it's going to be really
hard to maintain. And not only that, it's
going to increase, like I say before, the file
size at the application. How do we get around
this problem here? Or shop has something we can utilize and that is
called inheritance. Inheritance in C Sharp, it's very easy to get started, but perhaps more
complex to master. But let's get started and have
a look how we can do that. We don't need any of that
functionality in our class. What we can do is inherit the functionality of
the animal class. All of this can of stuff here, all of the public stuff anyway. And we can go to our dog class
and we can use a colon and then type in the
class we want to inherit the features from. In this case it's going to be
animal just by doing that. One very small
piece of code here. Now our dog class
knows about all of the public methods here and any public properties we
may have in this class. Let's take a look at an example. Right now, you can see our
dog class is perfectly empty. Our animal class
has all this logic. Let's create a new
object for a dog and see if we can
actually use some of these properties and
methods right here. Let's create a new
object for a dog. I'll just call him Do. We
can set the name to the dog. Bingo, why not the dog's age? We can set it to
three, for example. I'm just going to rename these. You can see here, there's no red lines under
these properties. There's no errors
using these methods. We can even run the
application, no problem. And now, look, my name is Bingo. I am three years old. You can see here, the dog has inherited all of the
functionality from animal, all of the public methods
and properties from animal. You can see here's the
dog class right here. It's totally empty. But you can see we're re
using all of this code here which is really
efficient and that is the point of inheritance. In this example here, we say animal is either
the parent class, like how you have a
parent and a child, where the child might inherit
the ability to breathe, or bleed, or eat
things in your DNA. This is where the
terminology comes from. The animal in this case would be the parent and the dog
would be the child. But some other synonyms
for that would be the base class
or the superclass. Dog would be the child, the derived class
or the subclass. They're all synonyms, but they basically mean the
same kind of thing. When considering
inheritance in C Sharp, you have to consider one thing, one thought must be
going in your head, and that is a is a dog, an animal is a cat. An animal is a rat, an animal. If so, then inheritance
is perfect for you. And you're not
misunderstanding the concept. Always consider when you're
inheriting in a shop is it's an is a relationship. Inheritance is a really
lengthy subject. But one other thing I'm
going to explain so it's absolutely clear
what I'm going to do. I'm going to define
a method inside our dog class which
is unique to a dog. I want that to be, maybe
bark, for example. Because all dogs bark, let me create a method
where the dog would bark. So you can see I've created
a method here called bark. And all it does, it writes
to the console window. Woof, woof. So very simple. And just like in
humans, if you have a, you can inherit things
when you're born, like I mentioned before. But the parent can't
inherit from the child. For example, if the child has a new ability like
barking for example, then the animal has
no knowledge of this. Just like in a parent,
child relationship, if your child has a new skill, maybe they became an artist. It doesn't mean the
parent's an artist. You know, inheritance
doesn't work that way. So let me show you an
example of that now. So we've defined a method in
the dog class called bark. If I go to our main cannon
program right here, if I put a little dot
after animal here, you can see animal has no
knowledge of the bark method. It's not even in this
list that's expected. However, if we go to the
dog here and type in, do we have our method we've
just created called bark? We can run the application
now you can see that you can. So the dog is barking and then we're just echoing the name and
the age of the dog. That is a very basic example
of inheritance in a shop.
44. 9-7. Method Overriding (Polymorphism): Okay method over riding. If you haven't seen the previous
tutorial on inheritance, then I highly suggest you
watch that because it follows on from that
what I have here. I have a basic animal class. We're giving the animal
class a name and age. Now I have a dog class. And again, the dog
has a name and age and also a cat
class right here. And they do various
things with the animal. I'm saying the name
age and making a noise same for the dog
and same for the cat. If I go to my animal class here, we have the usual things, the methods from
the last tutorial. But also we have one more method here and it's called make noise. All that it does is
echoes something to the screen that says makes
random animal noises. I have a dog class that
inherits from animal. It inherits all the public functionality we
have defined her. And a cat class that also inherits from animal,
but they do nothing. The cat and dog classes are
doing nothing Right now, if we run the program, you can see here,
my name is Henry. I am five years old. Makes random animal noises. And it does the same for
the same for the cat. What we're doing here, we're inheriting all of
this functionality. But you can see in
particular we're inheriting this method
here called make Noise. Now this is part of the
animal class, for instance, we might not know what
kind of animal we have, we just have a generic
animal called Henry. However, in my dog class, well, I know that dogs bark. For example S, I would
want Lassie to bar. I don't want Lassie to
make random animal noises. Same with the cat
class. We have Felix. I would like the
cat to for example, I could easily do
that by defining a new method here called
bark in the dog class. Then in the cat class, I can define a method
called make noise or per, or meow or something like that, which is unique to a cat. But what we can actually do is override this method
here called make noise. What that means is we can inherit this noise
functionality. But it's not going to do this, it's going to do something else. That's something else we can
define in our child class. For example, the dog class. How do we override this method? How do we inherit
this and override it? Well, in the child
class here, dog, we're already
inheriting the method already because we're making
random animal noises. But we want the dog to bark. So how do we do that? What we have to do in the parent class, so in this case animal, we need to make the method
what's called virtual. And what that is, it's a
new keyword called virtual. And that just says, okay, anyone inheriting this class, you can give your
own definition to this method if you want
to. It's your choice. You don't have to right now. I'm not even doing that. I run the program, I'm inheriting
all this functionality. Virtual is basically
saying, okay, the option is there to
redefine your own content. For this method, it's optional, you don't have to.
That's virtual. But what we want to do, yes, we do actually want
our own functionality. For example, in this
child class here, do what I want to do when I call the make
noise method here. I want to bark. I
want the dog to bark. In order to do that, I say
bark or woof, or maybe both. Why not? I've copied
this method from above, but we don't put virtual here. We use a new keyword
called override. And that's again a
special keyword. In the base class, the parent class, we use
the keyword virtual. In the child class, we use the keyword override. That is basically saying, okay, I'm inheriting this method
from the parent class animal, but I want my own definition. I want to override your
cano logic and put my own override always
goes in the child class, in this case dog. In the base class, we have
to set it to virtual. If we don't put virtual, then we can't override it. They go together like a
pair in our cat class. Well, I want the cat to me now, For example there, it's as simple as if I
run the application. Now you can see here
my name is Henry. Now Henry is a generic animal. He's not a dog or
he is not a cat. Henry makes random
animal noises. However, Lassie
or Less is a dog. When we call the method make
noise here for the dog, then the dog is going
to bark and woof. Well, the cat's
not going to make random animal noises because the cat class also overrides
the virtual method. Make noise and the
cat is meowing. You can see that's
quite a basic example of how we can reuse
this method here, make noise which is defined
in our parent class, but give our own
definition to it. This is reusing existing
code like this method here. But we don't want this
functionality, We want our own. The process of defining
our very own definition is an example of what's
called polymorphism. What is that? It's
a Greek word that means many forms or many shapes. But it's a key principle of
object oriented programming. So you've been
doing an example of polymorphism this whole time,
maybe without realizing. But this is the key principle
of 00 programming and it's very important like
you've seen already. It's achieved through
inheritance and reusing code. But not only that, but providing your own
definition for something. So this is polymorphism. So this is an example of
method overriding in C sharp.
45. 9-8. Multilevel Inheritance: Okay, multi level inheritance. If you haven't watched the previous tutorials
on inheritance, I highly recommend you watch
them now because it follows on from that multi
level inheritance. So let's look at an
example right here. Here I have an animal class, Here it is right here. It defines some basic
things to do with animals, especially this method
here make noise. Now, this method is virtual, which means any child classes of this base class animal can optionally define their own
content for this method. Okay, we've talked about this, now we have two new classes. One called carnivore and its parent class is animal
and one called herbivore. The carnivore is like meat
eating and a herbivore is plant eating and a
herbivore is an animal. So is it satisfies that
kind of relationship. And the herbivore
overrides the method of the parent class animal and defines its own functionality, which is I'm a herbivore, makes plant eating noises, and same with the carnivore. It's overriding
the virtual method and defining its own code. I'm a carnivore makes
meat eating noises. Okay? If we create
an object which is a carnivore or a herbivore
and run this method, we're going to get this result. Now, cat and dog. Now, cat is a carnivore. Dog is also a carnivore. You can see what is
happening here is the dog is almost like the
grandson of animal. Carnivore class sits
between dog and animal. The base class here is
animal, then animals, child is the carnivore, then the child of
carnivore is the dog. That's an example of
multi level inheritance. We have a hierarchy here. We have the grandson, the dog. The father is the carnivore. The granddad would be
the animal for example. There's multi layers
of inheritance here, you can perfectly do that
you find in C sharp. This is just an example. You can see here dog also overrides the
method make noise. It's doing bark, woof. So let's take a
look at an example. Here I'm creating a new animal, that's the base class,
like the granddad. I'm creating a new dog which is like the grandson and a new cat, and then I'm calling the make noise method on each of these. I don't have a carnivore object. I don't have a herbivore object. Let's run the application here. Makes random animal noises because we don't know
what animal Henry is. That's what we've defined then. Dog and cat have their own
definitions for make noise. Bark, wolf and O, what happens if I remove
this method here from dog? What happens? Am I
inheriting carnivore? Am I inheriting animal
like the granddad of this? Well, I'll show you right now, it inherits the parent class, so you can see now I don't have a method called
make noise in dog. When the dog makes noise, it looks at its parent class, and in this case it's carnivore. Carnivore is actually
overriding make noise and giving its own definition
when we run the program. This is Henry, the
random animal Noise. Let's just put that
in view there. This is Henry, this is the dog. Because the dog class is
now not overriding this. Now it jumps to its parent, which is carnivore
that does override it. Now the dog is saying, I'm a carnivore, makes
meat eating noises, and the cat still has its own overridden method defined so that the
cat is still meowing. But that is a very
basic example of multi level inheritance in C Sharp and how we
can utilize that. How many layers of
inheritance can you have? How big can build this animal
family tree for example? Well, there is no
real set limit, but when making software, you don't want to make it
absolutely ridiculous. 234 levels maybe, might be depending on the
size of your application. So having ten or 50
levels of inheritance, I can't think of an example why you would
ever want to do that. But the purpose of this
tutorial is just to show you like this is possible
and you know it's, people use it in the real world. There is one other type of inheritance and that's
called multiple inheritance. That's where a class, for example, like cat, can inherit from not
only, for example, animal, but maybe something else like feline or something. So two classes. Now, shop
doesn't natively support this, but it can be achieved
through interfaces, which we're going to discuss
in a later tutorial. So there are different
layouts for inheritance, but this is just an example
of multi layer inheritance. So can I get you started with? I hope this tutorial helped
you consider many of the possibilities with
inheritance in shop.
46. 9-9. The sealed Keyword: I want to talk about the sealed keyword in shop
and it looks just like this. The sealed keyword is quite
useful for restricting inheritance at class level.
What does that mean? Here I have an example of multi level
inheritance in C shop. I have a game class which is like the mother, for example. I have video game,
which is the child. And then I have Super Mario, which is the grandchild. So it looks something like this. So here's the base class game. It only has one method
that says what is cool, and it's marked as virtual. So that means any
child classes of this can choose to override this
method if they would like to. Then underneath the
base class game, I have one called video
game that inherits from game and it does
override that method. But instead of saying
the game is cool, it's saying this
video game is cool. Then I have the
grandchild class in this application that's
inheriting from video game. It too is overriding the
what is call method. Now it says Super Mario is call. If I look at this
application here where I set up three objects and
just call those methods, it's just going to output the results of those methods,
That is polymorphism. What I can do with
the sealed keyword, I can actually restrict
inheritance on a class. Video game is like the
filling of this sandwich. Its parent is game, but its child is Super Mario. So for example, if I say
this was a sealed class, that means no other classes
can inherit from this class, so it can't have
any more children. Imagine it to be like maybe a phasectomy or
something like that. However you want to
try and remember that now if I go to
the child class, you can see now
there's a problem. Super Mario cannot derive from sealed class video game because video game can't have any
more children. It's sealed. It prevents inheritance
at class level here, what do I mean at class level? That just means on
this line right here. However, we can actually use
it at method level as well. And that restricts any further
inheritance on a method, not the whole class,
but just a method. We cannot put this in the base
class as a rule of thumb, we can never put this in the master class,
the ultimate parent. What we would do, we define a method here called
what is cool. We mark it as virtual. When something is
marked as virtual, that means the child
class can provide their own definition by
overriding the method. We've done this before. Now I go to the immediate child, which is video game. I'm overriding this
method, right? This is the first
time we're overriding this method because it's
the immediate child. This is where I can make
use of the sealed keyword. You can only use
sealed with override. You can't use it with virtual. It has to be at least
one level lower. Now I'm restricting any
further access to this method. What is cool now the
poor Super Mario class, it can no longer use this
method. You can see. So cannot override
inherited member, what is called
because it's sealed. Using the sealed
keyword prevents at class level any further
inheritance of the class itself. And a method level prevents any further overriding
of the method, as long as the method
is marked as sealed. So that's the power of the
sealed keyword in C Sharp.
47. 9-10. Abstract Classes and Abstract Methods: Let's talk about abstract
classes and abstract methods. What are they? Why
should we use them? Let's take a look at
this example here, following on from before. If you haven't seen
the other tutorials, I highly recommend you watch them because they
follow one from those. We have our base class here, animal, and we're just setting
up an animal name Henry. We have our dog which
inherits from animal, and again a cat that
inherits from animal. And we're just echoing
the name of the animal, the dog and the cat. Here's our animal class.
It's not doing much. We have three methods. We've marked, make noise, say age, and say
name. All as virtual. If the child classes want to
override these, they can do. We're now overriding same name. If we get the dog's
name, it's saying, oh my name is then the dog's name and
then woof at the end. And same with the cat.
Not much is going on. We haven't really
built on it that much. We run the program, this is what you can
see, for example. It's quite normal. Now imagine that you have a very
large piece of software. You have ten other people
working on the software, and you want a class
for each animal. You're emulating a
zoo, for example. You're creating a
piece of software for a zoo or even a Pokemon game. And you want a class for each
character or each animal. You could have one person on your team create
all these classes, but in teams of maybe
ten or 100 people, you're going to
delegate that out. You're not going
to be the only one creating these classes. In these classes here we have one that says make noise and
it's barking and wooffing. We have one that
says say the name and it's saying the
name of the animal, for example, the dog here. And the dog woofs after echoing its name.
Same with the cat. But what if our teammate Randy, for example, he's
creating a hamster class. Maybe he forgets to
override this method. He remembered to say the name, but maybe he forgot to
make the noise when the application runs rather than overriding make noise and
it's making hamster sounds. It's just going to
make the default can apparent class sound here,
random animal noises. So how can we tell
Randy, our friend, and you forgot to
override this method, make noise, your hamsters
not making hamster noises. Well, we can actually enforce this in our parent class animal. What we can do in animal, we can say, okay, I'm going to draw up
a contract and say any class that inherits
this class has to override, say, these three methods here. Otherwise the software
won't even compile. We can't even run the software that make sure that
our friend Randy, for example,
overrides the methods we want our friend
Randy to override. We can introduce something
called abstract classes. To achieve that, what
abstract classes do? Imagine it as okay, if I want an abstract class
and an abstract method, any class that
inherits this class here has to override
those methods. They have to specify
a definition. If this is an abstract method belonging to an abstract class, then if Randy, our friend, creates a Hamster class, then the software
won't even run. If he doesn't provide his own definition for these methods, that's the advantage of an abstract class and
an abstract method. I'm going to show you
how to set that up. Now the first thing
we do to set up an abstract class is to
mark the class as abstract. That's just as simple as writing the abstract
keyword there. That does a couple of things. Once we mark a
class as abstract, we can no longer create an
object from this class. What does that mean? If we
go to the program here, you can see we're creating an animal object
here called Henry. Now we don't know
what animal Henry is, he's just been used
in our example. But you can see here
now there's a red line underneath this new
instance line right here. When I hover over that, it says, cannot create an instance of the abstract type or
interface animal. That is because if you mark
any class as abstract, you can no longer create
an instance of that class. Now, Henry, we're going
to have to decide what kind of animal
Henry is at this point. He's either a dog, a hamster, a cat, or something else. But now we've marked this
animal class as abstract. We cannot create an
instance of animal. Henry is going to have to go and we're going to have to make
a decision on what Henry is. But that is by design. If you have an abstract class, you can't create an
instance of this class. Now, abstract method. So we have our
abstract class set up. Now we're going to create
an abstract method. Like I mentioned, if
a method is abstract, then any child class inheriting this class must
provide a definition. For example, our dog class do
class inherits from animal. What I'm going to do, I'm going to delete these two methods. Dog is just inheriting
the normal stuff. Now, I'm going to mark
this method as abstract. This is an abstract method. When I mark a
method as abstract, we cannot provide a
definition for the method. Like I mentioned before, it enforces in all child
classes to provide their own definition because we can't even create
an instance of this class and we're
just enforcing child classes to provide
their own definition. Then there's no
sense in even having a definition here
because it's irrelevant. It would never get
called or reached when you define an
abstract method, it's just a template. It's just saying, okay,
all child classes, you need to provide your own
definition for this method. In the cat class, we're
doing exactly that. We have our own method here and we're overriding it when you define a method as abstract in order to provide
your own definition, just like virtual, you use
the override keyword here. Now in the dog class, you can see there's an error. If I hover over dog
here it's saying look, dog does not implement inherited abstract member
animal make noise. You can see the software
isn't even compiling. We simply cannot
compile the software. That is the reason
what we have to do, we have to define that method. Our friend Randy who forgot to his definition for his hamster
making hamster noises. Well, now the software
physically will not compile unless our teammate remembers to overwrite
these methods. That is a very good use of
having an abstract method. We can do this for
all of these methods. For example, for
example, say name. We can define a
template for that. You may ask yourself, what's the point in even
having a method? Then, for example, why
even have say, age well. That's because all our child
classes like cat and dog, they can still use
say, age in here. For example, we can call say, age in these methods, we can use them from any
child class of this. These methods are still useful. So this is a standard method, but this is an abstract method. The abstract methods,
we're basically forcing all child classes of animal
to implement something. To give it a definition, a function, that's what
an abstract method is. It's forcing all child classes to implement a
definition for them. However, we can still have normal methods like
say age for example. We can still use
virtual and have dog and cat override
the virtual methods. Those are perfectly fine, but that is the
point of abstract. So using abstract classes here, like animal, not only
enforces abstraction, which we talked about with
access modifiers earlier, but also polymorphism as well, where we can define our own can of function for these methods. Here, not only that, but abstract classes can enforce any child class inheriting from animal gives some functionality
to these methods, consider it like a blueprint or a contract or
something like that. I appreciate this tutorial
might be a lot to take in, but feel free to replay it over and over
until you understand. But this is the generic
principle behind abstract classes and
abstract methods in shop.
48. 9-11. The this Keyword: I'm going to talk about
this keyword in C sharp, it looks just like this. What this is, it's basically a shortcut for an
instance of a class. Here we have a class called dog, and I'm creating an instance. This can be a shortcut
for this instance here. If I look at my dog class here, it has one method
called make noise. When we call that method, it's just writing bark woof
to the console window. If we look at that, now
we're calling make noise. If I run the program, you
can see it doesn't do much. If I go inside this dog class, I can refer to this
current instance when this method
is being called. For example, I go in here, If I type in this,
I can refer to anything to do with this current instance which
is being created here. Let's look at an
example of that, just so I can prove it to you. I've created a class
called helper. Now helper doesn't do much. It has one method
called make more noise. It takes one parameter, which is a type dog, and there's the
instance of the dog. This is being passed in as
a parameter to this method. We're writing a line, I'm making more
noise for dog name. If I go into my dog class here, I'm going to create
a new instance of helper so I can
use the class. Then I'm going to use
help, make more noise. I want to pass in
an instance of dog. What I can do is pass
in the keyword this, because this represents
the instance which I created right here. When we call the method
on this instance. Imagine it being
remembered here. Now, this represents
that very instance. Imagine this being this. Now, when we call helper, we're calling the
method, make more noise. This instance is being passed
in. It's come a long way. Now we're just
echoing the name of the dog which belongs to
that current instance. If I run the program now
you can see barkworfI'k. More Noise What? It's blank because we haven't
given the dog a name. Let's give the dog a name. So, dog name. Let's, let's call him Rocky. Why not Now the dog has a
name. Let's run it again. Now, I'm making more
noise for Rocky. You can see that's the
power of the keyword, this. It takes the current instance, it's basically a
shortcut for it. Imagine this being a shortcut
for the current instance. And we can do whatever
we want with it. We can access,
access properties, access any private fields, or even pass it to different
methods as parameters. That is the power of
this keyword in shop. Another thing we can do with
this keyword in C Sharp. Here's a good example. I see people do this
a lot if we have a constructor for a
class like animal, and it takes in two parameters, for example, name and age. In our constructor, we want
to construct our object. What we do, we set our local field name to
the parameter, like this. Then we set age to the parameter
as well, just like this. Now we've done that,
We can actually use this keyword to differentiate
this instance of name. This is the parameter from
this instance of name. This is the private field. What we can do to make it
more obvious is say this. Now, this name
refers to this one, because this is the current
instance of this class, it's going to refer to
this one. Same with age. This refers to the instance
which is this one right here. However, name here refers to this one because it's not
in the current instance. It's being passed
as a parameter. You'll see this a lot when
setting up constructors, and it just differentiates the names so there's
no ambiguity. It's clearly obvious
what's going on. The current instance here
is equal to the parameter. You'll see this quite a lot
in your future endeavors.
49. 9-12. The base Keyword and base Class Constructors: The base keyword in shop. What is the base keyword? Now, you would use the base
keyword when trying to access from a child
class like dog. Here, this is a child class, we want to access anything
in the base class, hence the base keyword. Consider it like a short
cut for accessing methods, properties, and
things like that. Here, for example, I have a
base animal class here that has a couple private
fields and some methods. For example, this method here, it's called animal method, it's public and it's part
of the animal class. What I can do from
the child class dog, I can come in here and
say base and then I can access animal method because this is a child
class in this case. Base is optional, but you
can see how it works. It adds a bit of clarity. For example, what I have here, I have a method
called info that just outputs to the screen some information about
this current dog. If I go over here, I've created a new object here,
a dog instance. I've given it a name, an age and a breed. And then I'm just
outputting the info here. So when we run the program, we can see some
information about the dog. What you will see a lot is just adding a bit
of clarity because name and age are both defined in the base class animal here. So you can see name, age, it adds a bit of clarity. If you look at the code, you can quickly see, oh okay, these are members of the
parent class to look there. However, Breed is a
member of this class, so it doesn't have
the base keyword, But you can see quite easily you know where these belong just
by looking at that keyword. But that's not the main
feature of the base class. What I want to talk
about now is if you have a in the parent class,
for example, animal. If I set up a constructor
in animal this, you can see there's a bit
of a problem with that. If I now try and
run the program, it's not going to let me, if I go over to my child class, any of the child classes, this error has appeared. This little red line. If I hover over that, there's a bit of a cryptic
error message here. Now, by default,
constructors are not inherited because they're not
really members of a class. But now I've defined a
constructor in animal here. Now it's having a problem. I can't even compile
my software. What we're going to
do here is define a constructor in dog here. Way when I create
my dog object here, I don't have to set
all these properties. I can just put
them in parameters here when creating
our new instance. Let's have a look at
how we can do that. When we create a dog object, I want to specify a name
which is in the parent class, an age which is also in the parent class,
and also a breed. I want these as
all parameters and breed is part of the dog
class, not the base class. If I go over to the
dog class here, the child class, I start
creating a constructor. I want to take in
the name of the dog, the age of the dog,
and also the breed. It looks something like that. Now there's a shortcut here. What we can do here is pass name and age to the base class. How we do that is after
the constructor here, we put a colon and
put the keyword base. Then open and closed
parentheses in here. This pretty much calls the
constructor of the base class. Our constructor here
takes two parameters. Base in this case
is a shortcut for the constructor of
the parent class. The constructor takes
in two arguments. If we go back over here, it takes in the name, it takes in the age. Now we're dealing with
these two parameters here. They're being thrown up to the base class and the
constructor is called. Then we just need to
do something with the breed, We set that here. Now we can set up our parameters here when we're
creating the new instance. Now we don't need any of that. Essentially, this is going to do exactly the same thing
if I run the program. Now you can see it outputs
all of the information. One more time, how
does that work? We're creating a new
instance of the dog class. We're calling the
dog constructor, which takes in three parameters. Here's our dog constructor. Yes, it does take in
three parameters. Once the constructor is called, it takes in these two parameters and throws them up
to the base class. Up in the base class, you can see there's
two parameters, Here it is, calling the
constructor with two parameters. We only have one constructor, It has two parameters
then this is called. This sets our properties
here, name and age, which subsequently set
our private fields through getters and setters. Once the constructor
has constructed our animal object flow goes back out and then the rest of the
dog constructor is called. Which just sets the
local field here, breed to breed here. That's essentially how it
works in the background. It's just calling the
base class constructor. Write here, you may be asking why can't we
just remove that? And I do base name equals name and then
the age for example. No, it's not going to work because this
terminology up here, the colon base is
actually calling the constructor of the
parent class itself. So it is required and then that error will resolve
itself without that. And even if you put
those bases in there, it's still going to throw
this error here because the parent class's constructor
is never constructed. So it doesn't
actually ever create this animal object because
this is the parent class. The child class dog
depends on this. This is why it's required here. And that is the power of
the base keyword in shop.
50. 9-13. Interfaces: Interfaces in shop. Interfaces are another way to achieve abstraction in shop. We talked a little about
abstract classes before. Abstraction is a key object
orientated principle, which is just the
process of hiding the internal details and
showing only the functionality. Let's take a look
at interfaces in shop as a mini refresher. I'll just refer to
this project where we made an abstract
animal class here. Here's our abstract
animal class. We have some private fields and public methods here and also
some public properties. I have one abstract method here, because the dog class here is inheriting from the
abstract class animal, it has to override
this abstract method. It's forced to do that. And that's the point of abstract classes
through polymorphism. We're overriding this
method, make noise. And we're just outputting woof, woof for our dog class. When we create a new dog
object and run the method, make noise, we just
get woof, woof. In principle, that's the
abstract class there. We're forced to override
these abstract methods. Here, let's take
a look how we can create an animal interface and also see how interfaces differ from abstract
classes as well. Interfaces in shop, quite
similar to abstract classes. What I'm going to do is create a brand new interface in shop. Then I'm going to show
you a few differences between abstract
classes and interfaces. Then our dog class here is going to use our
brand new interface. It'll all become
clear momentarily. If we go over to the right
hand side here to our project, right click, go to Add,
and then go to class. From the menu here we
just choose Interface. Now we can give the interface whatever name we would like, but I want to create
an animal interface. When creating
interfaces, it's always good practice to use a
capital I beforehand. That's because when
you add interfaces, or at least you have a
really large project with maybe tens or
hundreds of interfaces, you can distinguish them
from normal classes. Here we have animals and
you can see animals. This one's clearly an interface, just because we've
named it that way. It's just good practice. The difference between an
interface like this one here and a class, this one here. Here's just the difference
in the keyword, which is we have a
class keyword for a class and the interface
keyword for an interface. Pretty much anything else
right here is the same. That's the only subtle
difference here. Now interfaces in C sharp, you can consider them as pretty much 100%
totally abstract. What does that mean?
Well, if you've watched the abstract class tutorial
like this one here, we have some abstract
methods here. When we have an abstract method, we don't define a body for it. Because our classes that
inherit this abstract class, they define their own
methods for them, like the dog class and the
cat class for example. They provide code. When we go to our
abstract class, it has no body for example. However, an abstract
class can define its own methods like
say name, say age. They can do various
other things as well. This is not true
with interfaces. Consider an interface as a purely abstract class where
you don't define bodies. There is a little exception for that rule to do with
private members, but I'm going to discuss that perhaps later or
at another time. Consider interfaces as like
a purely abstract class. We're not defining bodies in
interfaces for our methods. If I come over to my
dog class right here, which is inheriting from
this abstract animal class, you can see I'm overriding a make noise method and then giving it my
own functionality. I want to do the same kind
of thing in my interface. In my interface, I want to define a method
called make noise, which is going to be abstract because that's the
purpose of the interface. If I define a new method called
make noise like you say, because it's abstract, I
don't have a body here. And by default this is public. The access modifier
is public by default. And this is just by design of interfaces because we want everyone to use
these interfaces. So just like that, we've defined our very first method
in our interface. Very simple, isn't it? Because it's public and
abstract by default. We don't need any access
modifiers like public. It's optional and we don't
need the abstract keyword. For example, this
is how to define a public abstract method in
C Sharp for an interface. Now I go over to my dog class. Right now it's inheriting from this abstract class and
I'm all right here. I want to implement
the interface. So I'm just going to
put an I in front. So it now uses our interface instead of our abstract class. Now, how do we can rewrite this to make it work with
our interface here? Well, when we inherit from an abstract class and we
have an abstract method, just like we talked
about before, we use the override
keyword here. But with interfaces we don't
use the override keyword, it's not needed at all. This is perfectly sufficient. For example, one other thing. If we choose not to define a method for our interface
and just leave it like that. If we hover over this here, it's saying dog
does not implement interface member make noise
just like abstract classes. It's forcing us to provide
an implementation for that method so it can
force us to do that. When you have large teams
of people for example, it's quite handy because then all your classes are
somewhat standardized. And then you all will override this make noise method here, just like we talked about
before in abstract classes. Now I have this dog class here. It's implementing the make
noise method which we defined in our interface
and through polymorphism, it's defining its
own functionality. If I go over to the program
here where we create a brand new dog object
and we're calling the make noise method which is available
through the interface, we're going to get
exactly the same result. So let me just go over some similarities and
also some differences between abstract classes in C shop and also
interfaces as well. Because perhaps on the surface, they achieve a
very similar thing before when we try to create an instance of an
abstract class. It wouldn't let us.
It's not possible, and this is through design. Even if I try and
do the same thing with an interface for example, it's not going to let me even Visual studio isn't offering an autocomplete
feature for this. When I hover over this new
instance attempt here, it's saying it can't
create an instance of the abstract type
interface animal. So it's not possible. In an abstract class, we can have a constructor, but it's only called
by the child classes, not anywhere outside of that inheritance chain
with interfaces. You cannot have a constructor
because you would never under any circumstances
construct an interface. The interface just
acts like a contract, so anything implementing
the interface can override those methods
that are available. No constructors in interfaces. If we want to do that, then
the purpose is we have a class and then we
implement an interface, or we inherit from an abstract
class and then define our own overrides for
these abstract methods. For example, this is
why we don't create new instances of abstract
classes and interfaces, and therefore we don't
need a constructor. Something else we also
touched on was the fact that abstract classes can
have fields right here, which you cannot have
in an interface. Again, in methods here we can define bodies in
abstract classes. However, in interfaces we can't because it's
purely abstract. These are some differences here. You may be asking yourself
the following question. Why should I even use an interface when in
an abstract class, for example, I can use fields, I can define method
bodies if I want to. Why should I use an interface? What's the point? It
seems more limited, yes. Maybe it's 100% abstract, for example, but why
should I use one? Well, interfaces
support the idea of multiple inheritance in
C Sharp for example. If I have an animal
interface like animal, I can create an interface called maybe carnivore
for example. Then our dog class can
actually implement from animal and iconivorre or maybe
something else like herbivore. So it can implement from
multiple classes up here, multiple interfaces, and you cannot do that
with abstract classes. So this is one of
the main strengths of interfaces in C Sharp. So let's take a look at
an example right now. If I come over here, I'll right click the project, go to Add class interface. I'm just going to
create iconivorre because the dogs a carnivore. It's also an animal. Maybe there's a better
way of representing this, but let's just go
through this example. So you can see the
point of this. In carnivore, I'm just going
to define a method called maybe eat meat because
all carnivores eat meat. Just like that. Again, it's abstract and public by default. That's all we need in this case. Now if I want to inherit or implement from
multiple interfaces, I separate the class from
the colon, just like before. And then put in the class or interface I want to
implement or inherit from. But if I want to inherit
from multiple interfaces, I just put a comma here. Then I can put the next
interface iconivor, for example. Now you can see there's a
red line because it does not implement our new member
eat meat, which is true. We haven't defined a
method to do that. If I go to here and
type in eat meat, now I'm implementing that
method here from iconivor. I'm implementing this
method from animal now. Everyone's happy,
there's no red lines, everything satisfied. I can then put my
own definition, something like eat meat. Then if I come over to
my application here, I just type eat
meat for example. Now this is the
method that we're implementing from our
brand new interface icon. Or eat meat. Oh, let's get rid of that because we can't create a new instance
of an interface. Now I'm creating
a new dog object and I'm now eating some meat. And that's a member
of our new interface. You can see here, this is a very quick example of multiple
inheritance in C Sharp. And it's achieved through
using interfaces, which is something you cannot
do with abstract classes. These are the benefits of both. You can see that through
using interfaces in C Sharp and also
abstract classes, we can achieve abstraction, which is a key object oriented
programming principle. Now testing your knowledge
of inheritance or maybe just querying that you fully understand this subject. For example, if I go over to
my main application here, I can create a new method here. For example, I'm going
to call it make noise. It's not going to
return a value, it's just going to
make some noise about our animals to the
console window. And it's going to
take one parameter here because dog implements our interface animal because we know through talking about inheritance before a dog
satisfier is a relationship, a dog is an animal. Similarly, our cat class. A cat is an animal, a hamster is an animal. Then we can just go over to
here and take in animal as a parameter because our dog implements this interface here. Then we can do things from here. We can say make noise. What we can do here, we
can create a dog object. Then we can pass our dog to this method right here
called make noise. Then, because the
dog is an animal, then this is going
to work, no problem. It's going to call
the make noise method on the object here, which is an animal. It is an animal. If I create a cat object, I can use this same method because cat would
implement animal. In this case, I could create a Dolphin class as long
as it implements animal. Again, I can call this
method, no problem. You can see this is the
power of inheritance, but also using things
like interfaces. This also works with
abstract classes too, just like before, no problem. As long as my dog class inherits from the
abstract class animal. You can see now if
I run this program, you can see it's now
saying woof, woof. Similarly, if I have a cat
class like this one here, it implements from animal the make noise
method and overrides its own kind of logic
here, which is O. Then I go to the program, I create a new cat object, then I want to make
noise with the cat. And as long as it's
implementing our interface, then it's going to
work, no problem. You can see the
power of inheritance and why we use interfaces. We just have to
pass the interface around the software,
for example, as a method parameter or
even a return from a method, or pretty much anything. Again, if I run the program, you can see through
polymorphism, we're overriding the make
noise method for dog and cat, but also using interfaces to pass that object
around the program. You can see it's quite powerful and the possibilities
are also endless. You can see here if I change this interface to our
abstract class here, go to class and make sure it implements
the abstract class. With abstract classes, we use the override key
word because that's the difference between
those and interfaces. We reflect that also
in the dog class. And then go back to
our main program here. Then run the program. You can see we've passed around an abstract class and it works exactly the
same as an interface. But there are
subtle differences, like we've discussed previously, between interfaces
and abstract classes. But this is an
example of both how they compare and also
the advantages of using interfaces to satisfy multiple inheritance in C Sharp. I hope this tutorial helped you, and thank you for watching.
51. 9-14. O-O Summary: So we've just completed
quite a few tutorials on object orientated
programming. Now we've gone
through pretty much every principle of the
programming paradigm. And now we're just
going to kind of come full circle and reflect
on what we've learned, and drop some keywords
and things like that. So again, like I mentioned at the start of our 00 journey, C sharp is an object oriented
programming language. And using 00 will really help you
structure your projects. When your projects
get very large, they're going to be a
lot easier to maintain. You're going to
practice a lot of code reusability
perhaps in the future. If you continue this journey, you're going to work
with other people. Perhaps in a company
that also understand programming. You're all
going to know and already understand the same techniques
for writing software. So you're going to hit the
ground running really quickly. So let's just go through some of the terminology again just
so you fully understand. And then we're going to move on to something a bit different. Object oriented programming. Again, it's a paradigm, which is a way of
doing something. We talked about classes. Now classes model
real world objects. So if you have a piece of
software about a library, then a class might be a book. Because a book is a
real world object, your book class should
be highly cohesive. That means the class
about the book should only be about the book. It shouldn't be about the
user reading the book. So when you have a book
class, all the methods, all the properties should
always be about the book. This is very good practice and your classes should
be loosely coupled. That means your book class
should be about the book. Your user class should
be about the user. And they shouldn't
really have much in common with each other objects. Now objects is creating a
new instance of a class. A class is kind of like the template with all the
methods and properties. And when we want to create
a new instance of that, you can have one or
thousands if you want. That is called
creating an object. So an object is just an
instance of a class, and when you create an instance, it's called instantiation. Now, inheritance, inheritance
promotes reusing code, and when you reuse code, it makes it more maintainable. We don't have to copy code and put it in every single class, because if we have
a class like dog, then it can inherit from animal. If we have a class called cat, again it can inherit
from animal. And a lot of these classes
will have the same features. So you're going to use and
write a lot less code. And when you write
a lot less code, that means your code will
be a lot more maintainable, a lot easier to manage. Not only that, the file size of the software will be minimal. And also testing the
software as well, you can have a lot
less code to test. So inheritance all in all is a very good
principle to practice. We talked about polymorphism, that weird Greek word that means many shapes or many forms, which we achieved with
method overloading. When talking about methods, how we can have
different parameters but with the same method name. But also more recently we
talked about polymorphism with method overriding In a
base class like animal, we can say make noise. Then when we inherit
from that class, in a dog, cat, hamster class, we can override that method and provide
our own functionality. We can see the result of that when we run
the application, like when using the, the dog will bark when using
the make noise method. When using the cat class, the cat will meow. We can reuse this same method but providing different
functionality. That is polymorphism. Last two. Now the last two people get
confused between the two because they're very similar
and they do go hand in hand. And that is encapsulation abstraction. Now,
encapsulation hides the internal functionality
of an object. It only allows access through
a public set of functions. For example, when
we talked about access modifiers
public and private, because we want to hide
our sensitive information, like our private
fields, for example. But only access them through
public methods so that way we can verify the data and make sure people aren't
breaking things. Things like that for example. And also sea shop properties. When talking about abstraction, it means displaying only
essential information and hiding the nitty
gritty details. And we did this through
abstract classes and also interfaces. So imagine like a coffee maker, if you want to brew a coffee, you press the
coffee brew button. If you want to start a
car, you turn the key. You don't need to
know how a starter in a car works, or an alternator
or battery charging. As a user, as a developer, you just need to turn the
key to make the car work. Similar with a coffee
maker, you brew a coffee, you don't need to know
how the electronics work, how the water is heated. All of that is
abstracted away from you, it's unnecessary
information. If you're just an end
user of these things, like a coffee maker or
the driver of a car, you just do not
need to know this. And that's abstraction. And we see this
in everyday life, every day, multiple times a day. And that is the
difference between encapsulation and abstraction. Again, both key object
oriented programming terms, but they do go hand
in hand a lot. And at times, it can often
feel like there's a bit of a blurry line between encampsulation and
abstraction for that reason. So congratulations, we've
gone through all of the principles of object
orientated programming. And if you choose to take up another language like
C plus Plus or Java, you can take these
principles across and hit the ground running
almost immediately. It is not tied to C.
Sharp is something very popular and also used across
many programming languages.
52. 10-1. EXERCISE - Drawing Pyramids: Today we're going to be drawing pyramids and we're going to be drawing them in our
console application type. And we're going to
let the user decide how big they want
their pyramid to be. For example, if the
user types in 45, then a pyramid is going
to be generated here. And it's going to
be 45 lines high, as you can see right here. It looks pretty
cool, doesn't it? However, if the user
enters the number five, for example, then their pyramid is only going to be
five lines high. This is a bit of an exercise. It's not only going to test your C sharp programming skills, but it's also going to
test your logical ability. How you can look at a problem
and develop a solution by breaking it down into little subgroups and then
attacking the problem. So I'm going to solve this issue and I'm going
to show you how I would approach this task so
that you can see how my mind works and how I approach
this particular problem. It's quite common
to see exercises like this when conducting
a job interview. For example, the interviewer might ask you how you develop a small bit of
software to generate a shape or a pyramid or
something like that. Because anyone can look up syntax and code on the internet. But what a lot of
employers like to do these days is to test how your mind works, like
logical thinking. See if you can come
up with a solution on the spot and also
perhaps under pressure. So I'm going to develop a solution for this and
I'm going to show you how I think about this step
by step so that you can see how my mind works and
how I approach this problem. Let's get going. The first step is to analyze the problem. When the user enters a number, this denotes the
height of the pyramid. Not only the height
of the pyramid, but the number of
lines that are drawn. You can see there's
five lines here. The pyramid terminates when
there's one pound symbol, and the base of the pyramid
covers the whole line here. But you can see here, it's
the height of the pyramid, which is denoted by this number. The pyramid is five lines high, that's one thing to note. The second thing to note is that all of these squares
are populated. If they're not populated
by hashes here, the pound symbol
representing the pyramid. Then they're populated
by the background, which are denoted by hyphens. Here you can see the top of the pyramid has
one pound symbol, and then on both sides
it has four hyphens. The next line, you can see the pyramid increases
by two instead of one. Here it's now three, and then there's one less
hyphen on each side. Again, below the pyramid
grows by two per line, and then the hyphen
shrink by one. We have a couple of rules here. Each new line, the
pyramid grows by two. And each new line, the hyphen, shrink
by one on each side. One last thing to
note is that in this example where I have
a pyramid height of five, we have nine characters
along the width here, five down and nine wide. We have a lot of
data to work with. Let's see how we can develop
a solution for this example. If you followed our
tutorials previously, you may have seen the example we did when we drew a
cube on the screen. Now this exercise is
a little different, it's a little more complex, but the principles and procedures behind the
scenes are quite similar. In that example,
we use some loops, we use four loops. This example should be
no different When we see repeating data like this
and like this in our head, we should be thinking, okay, a loop must be involved. Something must be
looping around and iterating to generate
these hyphens here. Then we need another loop to then generate
these pound symbols. And then maybe a third loop here to carry on
with the hyphens. There are a few ways we
can approach this problem. Maybe we could have
one loop where we just switch the character
for the pyramid part. Yes, that may also work. When developing
solutions like this. There are quite a few
solutions to the problem, but the choice is yours. When you make that choice, you want to make the easiest, most time efficient one. But also generate the code
which is more maintainable, more maintainable by
yourself in the future, but more maintainable
by any teammates which actually take on your code
and develop it in the future. There's lots of things
to think about. I think the way I would approach this problem is to have a main loop going
down the y axis. We have a main loop which
generates each line in turn. Then inside that loop, I will have one loop that
generates these hyphens. A second loop that generates the pyramid
part, which is this. And then a third loop which
continues with these hyphens, one main loop which
does the y axis. Then inside that loop, I think three separate loops. That's a perfect solution for
approaching this problem. Let's take a look
at that now and see if we can develop
something like that. So here's the code
we have so far, it's not really doing
anything at all, It's just outputting some
messages to the user, welcoming them to the software. Thank you for using the app. This is what it does. And then we're asking the
user the question. We're taking the user's input, converting it to an integer, and storing it into
an integer variable. Now what I want to do, I'm
going to create a method. Because when I create a method, I can call it multiple
times from multiple places, and then I can generate
pyramids from wherever I want. I think all the logic for
generating the pyramid of the custom size here
should belong in a method. And then it's easily
reusable by anything else. I'm going to create
a method template. Now the method won't have a return type
because I just want the method to
draw the pyramid. It's going to create
one parameter and that's just going to be
the size of the pyramid. There's our basic method there. The first thing I
said I was going to do was generate a loop, which would print
each line in turn, and that would go
down the y axis. I'm going to create
a loop to do that. So this loop here represents
the height of the canvas. So the height of the
pyramid in this case, because the pyramid
touches the top of the canvas that we're drawing
on and also the bottom, it's safe to say
that whatever number the user gives the full
height of the pyramid, We have no background above the pyramid and no background
below the pyramid. Doing the y axis from one less than or equal to the
size of the pyramid and incrementing by one will
ensure that we draw the pyramid along the
y axis going down. Now inside this loop, I mentioned that a
possible solution was to have three
separate loops. The first one to draw the
hyphens on the left hand side, the second one to
draw the pyramid, and the third one to continue with the hyphens
on the right hand side. Let me set up those loops now without really thinking
about writing code. For example, I already
have this nice template. I've just generated
this template from just logically
thinking about the problem. I need some loop to draw downwards for the
size of the pyramid. Then inside on each line, I need something generating the pyramid and the background
on each separate line. Already, I have a
nice little template here without really thinking
about the problem too much. When we draw the
hyphens on the left, the only thing we want to do is output a hyphen to the screen. Let's do that now.
Similarly, when we draw the hyphens
on the right, we're going to draw a hyphen. Similarly, when we
draw the pyramid, we need the pound symbol. Pretty much the only
thing we need to do now is work out when
these loops terminate. When we looked at the
example before and the user entered number
five for example, then the pyramid had
a width of nine, but a height of five. The very first line of the
pyramid had one pound symbol, but it had four
hyphens on each side. We need to work out when
to stop drawing hyphens. To work out when to stop drawing hyphens on
the left hand side, we need to work out when to
terminate this fore loop. Similarly, how wide we
should draw the pyramid on each side and also when to stop drawing hyphens on
the right hand side. And when developing
software like this, some days you'll have
ultimate clarity. This will be easy for you, you just type in the values. You know, you're
having a good day. But sometimes if I'm just tired or I'm not in
the right mindset or perhaps you're a
beginner and you know you're kind of working
through it in your head. Well then it's no shame
using something like Microsoftic cell or a
note pad just to plot all your figures so then you can use your spare
brain space to work out a solution for the problem or perhaps
anything else. So there's no shame making nodes or anything like that,
it's perfectly normal. Let me open Excel and plot
some of these figures here. I've opened up Microsoftic Cell here and I've mapped
the solution here. Well, unexpected solution. Anyway, if the user enters
the number five for example, then we know our pyramid is
going to be five units high. When the user enters five, it's going to generate a pyramid that looks just
something like this. The solution we've
developed so far. I have a loop which
prints each line in turn. That's our main loop. We denoted that with y. You can see here
I just called it the variable y, y equals one. And it goes all the way to
the size of the pyramid. Less than or equal to
what I'm going to do. I'm going to put the
variable y right here. The next thing inside this loop, I have three loops. One will generate this content, the next loop will
generate this content, and the third loop will
generate this content. I'm also going to
put that over here. This is going to be the
first set of hyphens one. This will be the pyramid, And this is the second
set of hyphens. Now when y is one, this is the first
time our loop loops. We want to generate four
hyphens on the left, we want to generate one
character for the pyramid, and also four hyphens on
the right when y is two. Now our loop is repeating for the second time we're
generating this line. Our first loop will
generate three hyphens. Our second loop will generate three segments
for the pyramid. Again, the hyphens are going
to be the same on the right, then three and then
the third line. You can see where
this is going two, the pyramid will be five
and the hyphens two, then line number four
and line number five. I'm just going to fill out. Now you can see
here's some figures on how many characters will be printed for each
iteration of the loop. Now using this, you can work
out what you need to do. You have more clarity
in your head. You don't need to
remember these numbers. You can denote your brain power to thinking about a
solution to the problem. Let's look at generating a
solution to this problem. When the user
enters number five, then five is the
size of our pyramid. Our variable size, which
comes into our method, will be five the first
time the loop is run. Remember y is our loop. The first time the loop is run, y is equal to one. We can see that when y is one, the number of hyphens
on each side here is one less than the
size of the pyramid. The second time the loop is run, you can see the hyphens on each side is two less than
the size of the pyramid. You can see a bit
of a rule here. You can see that
when the size is five and we subtract
one from the size, we get the number of
hyphens on each side. When Y is 25, take away two is 35, take away three is two. You can see to
generate the number of hyphens on each side, we take the size
of the pyramid in this example is five and
subtract y from that. That will give us the number
of hyphens on each side. Let's look at generating
those hyphen loops. These are the two
loops that generate the hyphens on the left
here and also on the right. We said that the
number of hyphens for each line is the total
size of the pyramid. And we subtract y from that. We just say size minus Y. To add clarity, we put
brackets around there, then it adds more readability.
I'm pretty confident. Now for each line, we're outputting the
correct number of hyphens on the left
and also on the right. What a lot of developers tend to do is run the application early. There's a couple
reasons for doing that. One, you can see if your
last change was correct. And two, you can just look at the current state
of the application. If anything, it
gives you a bit more enjoyment to see what
you've done already. Let's take a look. Now, we're actually calling the method, now We're taking
the user's number. We're calling the method, and then this method
is getting executed. Let's take a look at
the results so far. If I type in the number five, now you can see everything is on one line. So why is that? That's because after all
of these three loops, we're not actually
outputting a brand new line. There's a bit of a
problem here also. Every time we
output a character, we're outputting a
brand new line two. That's also a mistake. Every time we
output a character, we don't want to
write a new line, we just want to write
that character. So we use console to do that when we actually
want a new line. Well then we're going to do that after all of these loops. Let's take a look
at the application now and see what it looks like. So you can see now we have
a bit of a rumbus shape. It looks quite interesting, but you can see that the
number of hyphens is correct. We start with 43210. Now we need to fix
this middle section here, which is the pyramid. Let's take a look
at how to do that. I'm going to go back into
Excel, I'm back in Excel. Now what I want to do
is find out how to generate these numbers using
our information available. We have the size of the pyramid and we also have the value of y. On each iteration of the loop, we've already done the hyphen
amounts for each line. It look quite simple to do, but how do we generate
this number using the information we
have on line one? Here, the pyramid
is one character, you can see there on line
two, the pyramid is three. You can see on each new line, the pyramid increases
by two pound symbols, 13579, they're all
odd numbers here. How can we generate
these numbers using the information
we have here? For those of you that
are good at mathematics, it's probably quite
easy for you, but sometimes developers aren't really good at
mathematics these days. Maybe in the '70s and '80s where all mathematicians
and physicians did a bit of programming, it was quite obvious, but these
days it's IT programming. It's a bit of a separate skill, Sometimes it doesn't translate
directly to mathematics. But if you notice here
with this y value here, let's take the number three. For example, if we multiply
three by two, we get six. And then we subtract
one from that, then we get the value five. Again, maybe four. For example, four times two is eight. Subtract one is 75
times two is ten, subtract one is nine. And I think that's
a rule that might work all the way
across the field, but we should always test
with 1.0 in cases like this. One times two is 21 is one. Yeah, that seems to work too. I think that might be
a rule that works. What we can say is p is equal to y multiplied by
two, take away one. That is a rule that should
work for generating the pyramid based on
the line number itself. There might be a lot more
solutions to this problem, but this is certainly
one that would work for us based on y right here. Coming back into our software, here we have the value of y on each iteration of the loop. What we do here, we want
to generate the pyramid on each line when y is
three, for example. Then we want to generate
five of these pound symbols. Here we said that is Y multiply by two and then
subtract one from that. It would look
something like this. I believe this would work, but to add a bit of clarity, I always use extra
brackets like this. It just makes it more readable so we can see what's going on. But you would get the
exact same result using this due to bid mass, because multiplication
comes before subtraction. But in cases like this, I would always write it like this. For example, let's take a look at the example now
and see what's going on. If we output the number five, input the number five, you can see now we get
a nice pyramid. That's pretty cool, isn't it? Does this work for
bigger numbers? Let's say 35. That looks pretty good. Yeah,
it looks like it's working. You can see this is how I would approach a problem on
something like this. We pretty much wrote 90% of the code by just
analyzing the problem. We didn't need to really think about C sharp and programming. We literally just
looked at the pyramid, dissected the problem a bit, and broke it down
into smaller chunks. The only bit that
was difficult was finding out the bounds
for these four loops. So how many hyphens
we should draw, how much of the pyramid we
should draw on each line, and again, the
hyphens on the right. And also a little complication about new lines and
things like that, which is kind of normal. Sometimes everybody makes
mistakes, it's normal. But you can see how we
isolated these problems and used Microsoft Excel to
sort of run the figures, so we didn't really have to hold all of this information
in our head. We can just sort of
take the problem here, dissect it all down,
run all the figures, then we just have to
work out how to get these figures from the
information we have, either the height
of the pyramid or the value of y on each
iteration of the loop. So you can see how we broke the problem down without
really thinking about it. We didn't really use
any brain power. Everything in our
mind was dumped into Excel and we can sort of work
out a solution from that. So that's how I would tackle
a situation like this. Especially if I was really tired or hung over
and I couldn't think, then, you know, let the
tools do the work for you. So coming back
into visual studio now we're drawing
pretty cool pyramids. We can even replace
the background with a nice empty white space. And maybe we can
draw two pyramids. I mean, we put it in a method, so now we can repeat the
method a lot more easy. And that's the power of methods. So if I now put in
the number five, for example, now we're generating three pyramids
on top of each other. That's pretty cool, isn't it? So anyway, that's how I would approach a
problem like this. Again, it's a common thing you may find in job interviews. But really the power of a programmer is to
test logical thinking. How does your mind work? A good programmer is
not somebody that can remember syntax and
regurgitate information. A good programmer is someone
that can think logically, break down a problem, and find a suitable solution. That is what a good
programmer is. So I hope you found
this exercise useful, and thank you for watching.
53. 10-2. Solutions, Multiple Projects and Namespaces: In this tutorial I'm going
to be showing you how to set up multiple projects
in visual studio. I'll talk a little about the
terminology like solutions, projects, assemblies,
and also name spaces. I can show you how to access files from different
assemblies as well. This will be very
useful moving forward. If we open visual studio, we can get this dialogue here where we can create
a brand new project. Here, we're going to click this, then we're just going to
create a console application. If I click next here, it's going to ask me for
the name of my project. Now because I chose a
console application here, this is what represents like
a graphical user interface, something the user might see. Similarly, you could have a
Windows Forms application, which is also a Gooey. But this is the graphical user
interface projects because it has a window that we can
see when naming this project. For example, it's quite common in applications
to have what's called a three layered
architecture where you have one project representing
the interface. Maybe on a website that might have HTML console application, it would have like
the black window and any logic to do with that. And then you have
a middle layer, sometimes called
the business layer, and that has all the
background calculations, all the logic, everything to do with the brains
of the application. And perhaps the third
layer will be like a database where all the
data things are concerned. The ability of getting
data from a database. You know, maybe it's paired to an oracle database
or an SQL database. So all things to do
with the data layer. This is what's quite commonly known as a three
layered architecture. When you create this project in C sharp here in visual studio, first we're creating
the guy here. And this is the console
application in this example. So I'm going to call it
something like that. Typically what I do and what other software companies do is when you create the guy, you might put guy in the
name of the project. If the project was called
test app for example, you might see
something like this, like test app guy. Or test a guy. Or perhaps guy test Ap,
something like that. From the name you know instantly that you're
dealing with the guy, the graphical user interface. So I'm just going to do
test Apoe, for example. You don't have to
do it like this, but this is good practice and
it's quite common as well. If you continue with
your endeavors, you'll see this quite a lot. I'm going to create
the project now. Here we have our guy. It doesn't really do much. It's just a black window that's
going to instantly close. But this project here, if we come over to the right, this project here represents
anything to do with our guy. Anything graphical that
the user might see, anything to do with the guy, all of that is
contained within here. You can see at the top
here, we have a solution. Now, solution can hold
a number of projects, maybe 102030, and we can add
different projects in here. So for example, let's
create a business layer. And this will have all the code, all the logic, all the
calculations, for example. Again, when creating a solution, if it's just a
small test project, for example, very tiny, maybe you're just
doing a quick mock up, then having a three
layered architecture is quite ambitious. It might not be needed, but if you know in advance it's going to be a large project or something that might talk to a database or have a
lot of complexity. Then you do need to consider
your architecture before you get started this
create another project. Now we're going to create
the business layer. So if I right click
the solution Add, I can go to a new project here. And when choosing the projects, I already have my guy here,
this console application. So I don't really
want another one, especially right now,
maybe in the future. It depends on my needs. Everyone's needs are different. But something for like a
business layer where you have code and pretty
much just pure code. Then you want something
called a class library. If I click next here, I can call the class library
again whatever I want. But if my application is
called test app like that, we might have something like
B L a business layer or LL a business logic layer
or something like that. Something representing a different layer
in the application. Typically I would do like
business layer for example. Then this project would contain all of the
business stuff, like the business
end of the system, if you see over here. Now we have two projects. We have our graphical
user interface. Now we have our business
layer here and that will contain all the calculations
and things like that. Now lastly if I write, click the solution again. I could add something
like a data layer, maybe a database project
or something like that. It could also be a
another class library representing the data layer. Something quite like that. You could say Dow for data access layer or
something to do with data. Or even DB for database.
It doesn't really matter. I could call it
something like that. Then this last project
here, this third one, would represent
anything to do with tying our solution to
a potential database, whether it's Oracle, SQL, my CQL, something like
that, it doesn't matter. And now we have three projects. Now, architecture, There's so many architectures available when
building software, like when building a building. There's not one way
to build a building. There's so many different ways, but this is a very popular one. What happens is if maybe you
have 50 people on your team, you work for a company. Some people will know
about HTML for example, but they're not going
to know anything about maybe a database or complex C sharp
calculations in this project. So what happens is they will
only work on this project. Similarly, if you're
a database person, then you will only work on
this database project here. Separating your solutions out by different projects also helps with teamwork and
things like that. Only people knowing
about the database, for example, would work
with this database project. That's kind of like some of
the reasoning behind it. How do I get my project
here, for example? This guy, How do I get it
to talk to this project? Because by default I've added three projects here
under the solution, but none of them are
talking to each other. How do we achieve that? If I go to my graphical user
interface, for example, this project here, I go
to dependencies here. Now, depending on the
version of Visual Studio, this is the newest one, right now, it's
called dependencies. If you have an older version, it might say references
or something like that. If you right click that and
go to Add Project reference. When I do that, a
window appears. Now I can see all
the projects in my solution as denoted
by this left hand menu. Here I want to check the projects that I
want to tie to my guy, say I want to talk to my business layer where all
the calculations are done. I just check that
there and press okay. And now internally, my
graphical user interface, this can now essentially
talk to this project here, the business layer where all
the calculations will be. Let's put a sample in here
so we can just do something. It's not going to do much. Set up a very simple method here inside what's called
the business layer. And what that is going to do is just going to return
the string hello. That is all it's going to do. I'm going to call it hello. I'm going to call
it hello class. Now inside our business
layer over here, I have a class
called hello class. It has one method, and all that method does is
returns the string hello. Now if I go back over to my graphical user
interface project here, test app guy and I type in, for example, hello class. You can see it's not
even in this list, but I've actually referenced
the project to this one. Why can't I access it? Well, this is where
name spaces come in. If you've been following
these tutorials so far, you'll see this keyword
name space quite a lot, almost in every file. And then it has a name. Typically the name
of the name space is automatically generated from
the name of the project. For example, this project
here is called Test App Guy. But if I go over to
my business layer, my business project I created, you can see it's
taken the name of the project here.
Now name space. It's just like a logical
way of organizing things. For example, we've talked before about the math
class, for example, where we do math art, absolute or square root
or something like that. But the math class, if I hover over this, you can see it belongs to a name space called
system right here. By default, when I create a
new project in visual studio, I'm given some name
spaces by default. All of these name spaces here, these seven, are provided
to me by default. Essentially, I can use any code which
Microsoft have provided me which is contained inside any of these
name spaces here, just like I have a
namespace here with a name. And I have some code in here. By default, I can utilize any code inside any
of these name spaces. This is very similar
to what we have here. What I need to do, well, I need to talk to the name space where I
have defined that method, because right now it's not. Here. You can see
where we've defined the method is inside a name
space called test app PL. If I copy that, I go
back to my guy layer, right here, right above here, I use a special word
called using what? Using does, it allows you to
use a different name space. If I just paste in
that name space here, followed by a sam colon, if I type hello class, now you can see I
have access to that, essentially by using
this name space. I have access to anything inside this name space,
inside this file. I hope that makes sense now, because hello class is defined
in test at B L namespace, as you can see right here, it's inside the name space. I can access all
of its features. I'm going to create
a new instance of hello class right here. Now I can say hello,
return hello. And that will get
me that string. This is how I can talk to a different class inside
a different name space, which is inside a
different project. Now for ultimate clarity, if I come over to
my solution here, I go to my test app
business layer here. And I go to a class
here, for example. You can say it has the
default name space. If I create a brand new class, I go right click, Add New class. I call it whatever I
want, it doesn't matter. You can see again, it has the same name space because
it's taken from the project. It doesn't matter how
many classes I create. By default, it will take the name of the project
for the name space. But you can rename
the name space to whatever you would like. You can see that's the
power of namespaces. In shop, you can have nested
namespaces, For example, a namespace inside a namespace, which is quite common
in visual studio. You can see there's a namespace called system inside of that. There's one called collections. Inside of that, there's
one called generic. Think of a name space as a way of grouping
things together. If you have anything
inside a project, which is to do with one
project, all your code, for example, in the
business layer, like the heart of
the application, that will be one project, one assembly for example. However, inside that project, you might have different things. Like you might have
part of the project to calculate the area of
a house or something, but inside that project, you might have something
completely different, like calculating a tax return. But maybe those two
things might have to exist inside the same
project for whatever reason. And in that case,
you would logically group them in perhaps a
different name space. So anything to do with working
at the area of a house, you might call that one name space and the
other one for doing tax returns or
whatever The example could be anything and that could be a different name space. So you're kind of logically grouping by maybe an activity or a function or whatever you decide when thinking
of projects, think architecture, like how
you structure your solution. But when thinking of namespace, think of more logical
things like how you group similar pieces
of code together. And that's sort of the
difference in this case. So I'm just going to show you one more thing with regards
to multiple projects, and assemblies and
things like that. Now, this is quite a
complicated subject, quite a large subject really. But what I'm showing you
is enough to kind of follow through the remainder
of these tutorials. But not only that, but when you start your own
solutions and projects, you have a general idea of how you're supposed
to structure things. And also how to
organize your code, which is very important the
bigger your projects become. Now if we come over here, we have our solution here with our three projects underneath. Now each one of these
represents like an assembly. It's a word you're
going to hear a lot, but when people talk
about assemblies and the internal
access modifier, then it's internal
to the assembly, which is typically
represented by a project. One project per assembly. Now if I come over to
this green play button right here, when I click this, our solution is compiled, all of our projects
are compiled, and an assembly is created
for each of our projects. So if I go to my
file system now, now I'm using a window system
for the guy project here. It's making a EXE
file right here. Again, some various
files with that. But you can also see
it's actually creating a DLL file here for
each of our projects. Now these are what's
called assemblies here, because we have three
projects in this case, we also have three
assemblies here. You can see behind
the scenes and how this is represented
in the real world. When you give this
software to your friends or maybe package it up
into a set up file, you can see how
these projects are represented as binary
files right here, typically one for each project. One thing I will mention
is that having this using keyword up here is somewhat optional if I decide
to remove it, for example, you can see this is no longer going
to work because it cannot locate the name space where this class is
contained within. What we can do in this case is just qualify it with
the name space. Every time I use Hello class, I have to tell the system
where it's located, like what name
space is it within? In this case, I can
qualify it with the name space before
the class name. But if I keep using
this class in this file maybe 1020 times, I'm going to have a lot of
kind of redundant code here. So rather than doing that, I can remove all of
those and just kind of use the name space
at the top of the file. And then I no longer need to qualify it every time I use it. So that's an advantage of using the namespace here, NC Sharp.
54. 11-1. Breakpoints and Code Stepping: Debugging, debugging in C Sharp. What is debugging If you've been following along
my tutorial so far, we've worked with the
C Sharp language, we've done lots of
different things. Object orientation, loops,
calculations, methods. But during these
exercises, for example, and working with the language, the fact of life is
that humans are human. They're going to make mistakes, whether it's intentional
or unintentional, or just a total accident. These things happen. This is
where debugging comes in. Now, debugging is a loose term. The word debugging is used
in two different senses. We can say, okay, I'm going to do some debugging, and this is the process
of trying to find bugs. Maybe your software has no bugs, but you're going to try
and find some just to make sure it works correctly.
This is quite normal. You also might use the
term debugging when your software has a problem and you're trying to
locate the problem. So you would say,
I'm going to try and debug my software because
there's an error. I don't know where it is, but
I need to try and find it. So it's used in two senses here. Now, like I mentioned, the fact of life is
no one is perfect. If everyone was perfect, then software companies
wouldn't even hire test teams to run tests. You wouldn't have something
called unit tests. You wouldn't need
to test your code. But the fact of life
is we're not perfect. And this is why we
need to know about debugging and to try and
find errors in our software. Now, so far in this
tutorial series, we've been using Visual Studio. Now Visual Studio is great. It contains many tools, features, and we've barely scraped the surface,
to be honest. It has a compiler that
compiles our code. It has the IDE where
we can actually type in to create
projects solutions. It has that
autocomplete feature, also known as Intellisense. So lots of different things, but one other thing it also has is what's called a debugger. So a debugger is a
piece of software, a totally separate program,
written by Microsoft. And the job of the
debugger is to attach itself to another
piece of software. This is called
attaching the debugger. So what software does this
debugger attach itself to? Well, this is your
code, your software. Every time you hit that
green play button, your software compiles
in the background. If you're using
Windows, for example, it compiles into an
EX, for example. Then the debugger can attach itself to this EXE
file in this case, but not only your software. It can attach itself to another executing process
which your system is running. It's quite powerful.
So what is the benefit of this debugger attaching
itself to your software? What is the purpose of
that? Why would it do that? Well, when a debugger attaches
itself to your software, it allows you to
exercise a level of control while your
code is running. And it can examine particular
segments of code when things may go wrong while
your software is executing. Imagine that you can pause your software at
any point in time. Say your software loads, it's running a loop. For example, maybe a four loop, and you can just halt the execution midway
through the loop. Say you have a four loop
and it counts to ten. You can stop your software
at a moment in time, for example, when it's
just counted to four. So while the
software is running, you can go into your code
and inspect everything. You can see values of variables. You can even control
the execution. So manually make that fore loop do two more iterations,
for example. And you can do this yourself. Have you ever seen those
superhero movies where the guy is really fast and
the whole world is frozen? But because he's so fast, he can interact with
people in real time. Imagine that to be
like a debugger. The world is going
about its business. But this superfast entity, this super fast hero, can kind of fly
around at the speed of light and modify things
and control things. This is kind of how
a debugger works. It's quite powerful and quite entertaining to
use, to be honest. And the process of pausing
your application while it's running using the debugger is called entering break mode. And when I said you can
actually control the execution. For example, if your software is running and it's about
to run a method, you can skip this method
entirely by stepping over it and controlling the flow
of your software while it's running is
called code stepping. The debugger is actually quite a powerful
piece of software, and 99.999% of developers would use a debugger in
creating some sort of software. So let's take a look
at an example of that. Now, how do we enter this world where we are a fast superhero? And we can pause the software
and change things around, and change values of variables and skip methods
and all things like that. How do we do that? Well,
let's take a look. So if you've been
following along our other tutorials so far, when we write some code, we've been pressing this
green play button up here. When we press the green play
button, our software runs. And when we want to kill
it or terminate it, we either cross off the window here or press this red
stop button up here. So that's what we've
been doing so far. If you go to the left of
this green play button here, you'll notice a drop
down list here. By default it should say D bug, but underneath it
also has release. Now these two items here
are quite important. If we have bugs
selected in this list, then every time we press
this green play button, the debuger is also executed and it also attaches
itself to our software. For those curious, if you
select release in this list, then typically we use this when we want to give the software to someone else because it doesn't contain any debugging
information. But for now, let's
talk about debug here. Now this is called
a release mode. Right now, we want to
debug our program, we want to find some errors
and do some detective work. Typically, when we
develop software as a developer and we're finding errors and developing
our solution, we would use this
release mode here, bug. And this is why it's default. So like I said before, when we run the
application here and our software is running
in the background, the debugger, the
visual studio debugger has attached itself
to our software. And I can prove that to you
if I Open Task Manager. Here's my task Manager here, these are all the
applications I'm running. Here's Visual Studio,
but underneath here you can see the Visual
Studio debugger console. This is running in
the background and this is actually attached
to our software. But so far we
haven't really made any use of this in our
previous tutorials, but in this tutorial
and the next few, we're going to be using
this quite a lot. Now let's take a look at
the visual studio debugger. Let's have a look at doing
some debugging here. I have a sample application. When this main method runs. Here it's entering into a
never ending wire loop. The application is never
going to quit out. Every time this wire loop loops, we're asking the user to
enter a day of the week. We're taking their answer, storing it into a variable, then passing their answer
to this method here, depending what day of
the week they enter. We have a switch
statement that prints out a custom message depending what day of the week they enter. Quite simple, every time
it outputs a message, we're just entering a
blank line and then looping back again to ask them for another
day of the week. It's quite a simple
application with this application
here I have a bit of a problem when I
type in Wednesday. It's not giving me the
actual output I want. When I type in Wednesday, I want it to output
Wednesdays or myth, which it doesn't currently. For example, if I
type in Tuesday, I get an answer for Tuesday. But for Wednesday you can see it's telling me I
entered an invalid day. Now I appreciate this is a
very simple piece of software, but imagine this software
being very complicated. You might have 50 files. You might have methods, methods, calling methods,
methods inside loops. So you can see it can
get very complicated. So, let's take a
look at how we can debug an application like this. We know so far using our detective skills
that Tuesday works. So therefore, the code is
coming into this method. The switch statement is run and we're getting an
answer for Tuesday. However, Wednesday
is not working. So, there's a problem with
this code around this point. At least that's
what I would think. So it looks like when
I type in Wednesday, it's outputting this kind of
default section right here. Why is it doing that?
What I could do in this case is add what's
called a break point. If you come over to
this left hand side here, there's a gray bar. When I go anywhere
in this gray bar, you can see a gray circle there. If I click with the left button, it adds a red dot. So you can see right
here, this is called. What's setting a break point? Why is it called a break point? Well, when I run the software here and type in any
day of the week, you can see the code
execution stops to remember when I explained
to you what a burger was, and I said, it's like
that superhero that can modify in real time, you know, like the
speed of light. This is the debugger inaction. Now the debugger has
attached itself to our software by setting what's called a break
point, these red dots. Here, we can set as
many as we would like. Every time the code reaches
one of these red dots, the software will freeze. It will stop. Nothing
more can be done. If I try to open my software, I can't interact with it at all. It's totally frozen. And we have full
control at code level. This yellow piece here, this is what it's frozen on. And that's our first breakpoint. So nothing else can happen. It's frozen in time. So what we can do while
it's stopped here, we can actually inspect things. Look, if I hover over this, I can see the value
of our variable here. I can see the value of
it getting passed here. So it's pretty cool, isn't it? It's like interacting with the world while the
world is frozen. You know, feel the power. So this is the power
of a break point. It breaks the software. And I don't mean
break like break a glass cup or
break a glass vase. I mean, breakers in pause, like halt. Halt the execution. So that's what a breakpoint is. The next thing I
want to talk about is what's called code stepping. What is code stepping? Right now, our software
is frozen in time. It's frozen at this
line right here. The switch statement
hasn't been run yet. It's yellow, which means it's about to be executed,
but not yet. What we can do, we can manually execute the
next line of code. This is called stepping, and we can do this manually. If we come up here, you
see all these icons here. This one here, it
says step into, this one step over, this one step out. And this one step backwards. So lots of different
stepping buttons right here. But what is stepping? Well, for example, this
one here, step over. You see the keyboard
shortcut here is ten. If I press ten, that's going to step
over this statement. And what that means is
the code is going to execute to the
next line of code, or the next block of code
inside a switch statement. Here is taking in our input, which is pretty much
a garboard string. What should happen is this
line of code would be run because we don't have
any day of the week matching our input. If I press F ten, which is step over, you can see the code then
goes to this line right here. Now we've executed the start
of the switch statement, and now the software
again is frozen in time. On this line, you can see we don't have a break
point on this line, but that doesn't matter because
we manually stepped over. If we want the software
to continue executing, then we would press the
play button, for example. Then the software would
just keep running until it hits one of
these red breakpoints. But when we do
code stepping like step over step into all
that kind of stuff, we're manually executing
a line of code at a time, or a block of code at a time, like a switch
statement, for example. So that's the power of stepping, and that's just manually running segments of your
code in sequence, how it would normally
be executed. Now the software is
frozen on this line here. You entered an invalid day. If I press ten again, then now our console window
will display this line. If I open the console window, you can see this line
has now been executed, but again the software
is frozen in time. Again, on this
break symbol here, I press F ten again, and now we're about to write this line to the
console F ten again, and now the method is executed. That's pretty cool, isn't it? Stepping in visual
studio when working in C sharp is to manually
control the code, manually execute pieces of code. That's what code stepping is. It allows us to manually
execute lines of code. And we can do this ourselves. And we can do this by setting break points to
initially halt the code. And then we can
use what's called step commands to step into, over out and all
things like that. But what is the difference
between step into, step out, step over? What are these things? Well,
consider this example here. We've run the application, and I'm calling this
method five times in a row for no real reason other than
to show you the difference. If we run step into which is 11, then we're going to
step into this method. If I hit F 11, you can see the next
line of code to be run is the open curly
brace right here, followed by the
switch statement. I've stepped into a method, I've stepped in here. What we can also do is
step over the method. Just ignore all this completely. Maybe we know this
method is perfect, there's nothing wrong with it. So we can step over
this entire method. And then the next line to be
run will be this one here. Because we've steps
over the whole method, that's the difference between
step into and step over. We can just skip a
whole section of code. You may have guessed
it. What is step out? Well, we're in a
method right now. I can click step out shift 11 and we can completely
step out of the method. And we do that when we assume
the rest of the methods. Fine. We kind of want to
step out of here and get back where we were before and then step into
anything else. So that's the difference
between these step commands. Typically it's just step into
something like a method, or a class or
something like that, or a property, or we could
step over it completely. So just ignore it and
carry on with the rest. And if we find ourselves
in a method and you know, everything looks kind of good, then we can step out of it. So these are called
step commands. And the process of moving the codes execution is called
code stepping or stepping. So that's the difference
with those there. So now I've explained
breakpoints. Code stepping,
stepping commands. Let's try and find
our problem here. It may look quite obvious, but remember we said
Wednesday wasn't outputting the correct
message. So why is that? So let's set a break point on this switch
statement here because we know the problem is likely to be inside this
switch statement. So I'm going to run
the application now, and I'm going to type Wednesday. I'm going to hit Enter, and we're about to launch
this switch statement. Here's our variable here. I can hover over input, and I can see, look Wednesday. So now what's happening
is if I step over here, you can see it's hitting
this default case. So none of these cases
are matching Wednesday, but which seems
weird because I have Wednesday right here
right now, Wednesday. So if I hover over this
variable, Wednesday, oh, I see, look, the y is in a capital right
there. It's upper case. That's probably why now I've changed this
y to lower case. I hover over this variable here. It looks like it matches
correctly. So this should work. Now what I could do is
restart the application. You see this icon here
next to the Stop button. It says restart. What I could also do is stop the program or cross it
off and then run it again. This restart button
here, what that does, it restarts R code, but it leaves the debugger
running in the background. If you click restart, especially if you have a
large piece of software, it's slightly quicker
to get going again. That's the difference between the restart and the
stop play button. One thing we can also
do, for example, is to manually move
the code's execution. What the hell does that mean? Right now, we're executing
this line of code. It's just about to be run. We just step over that, and now we're about to
execute this line here. Essentially this
switch statement here is finished executing. What we can do is hover our mouse over this
yellow arrow right here. Hold in our left button, and we can actually move the codes execution right back to the start of
the switch statement, like it was never run
in the first place. That's pretty cool, isn't it? Imagine dragging the mouse
here as using a step command, like step over or into. But it allows you to step back, but not only one line,
but multiple lines. So it's a short cut for
those step commands. But it allows you to do it
in big chunks, for example. Now we're about to re, run the switch statement again, but we've actually
modified the code here and we haven't even
stopped our software. It's done in real time. It's pretty cool, isn't it? Now, if I step over using ten, you can see this line
is now hit right line. Wednesdays are mere, so it
looks like we fix the problem. It was just, it was just that
upper case y on Wednesday. So now what I can do
is just press F five, which is short for this
green play button. So now I think the
problem solved. I don't want to do
any more debugging. I can take away my
break points if I want, and then I can just hit
this green play button and that'll just let the
software continue as normal. So now it's saying Wednesdays
there, which is perfect. That's exactly what I want. If I repeat it again, we get exactly the same result. So it looks like we fixed
the issue with our software. It was just a one
character difference. It might be a minor change. But even things like a one character difference can bring, say, space X rockets down to the floor,
never reaching orbit. So it is very important that everything is
checked in pure detail. In order to do
that, a debugger is a very useful tool on how to
accomplish things like that. I'm going to introduce
one more example and a couple of other debugging
tools you may find useful. They are run to click
and run to cursor. So let's take a look
at this example here. If you followed along
the previous tutorials, then you probably
remember this example. Essentially, this example is
being asked for a number. You type in number 25, and then it draws a pyramid
which is 25 lines high. For example, because I put 25, it has 25 lines high. But you can see
there's a problem with the background for this pyramid. This right side here
is going on too long. It should look like
the left side here. After each line, you can see
the pyramid grows wider, but the background
shrinks just like this. But this behavior isn't being mimicked on
the right hand side. There's a bit of a
problem with this. Let's take a look at
what's going on here. Here's the example.
Here we're asking the user for how high they
want the pyramid to be. We're passing it into a method. We're delegating all the logic of drawing the pyramid
in this one method. Here we have our main four loop that draws out each line
of the pyramid in turn. Then we have 34 loops, one to do the
hyphens on the left, one to draw the pyramid, and one to do the
hyphens on the right. We know we have a problem with
the hyphens on the right. This is probably a
good area to set our breakpoint and have a
look what's going on here. If we run the software, we ask the user for a number. Let's start out
with a low number. Low numbers are easier to debug because there's
not many of them. I'll type in the number five. Our breakpoint has
been hit here. Right now, H isn't declared. Let's press ten to step over. And now we've initialized the
header for our four loop. Right now we're about to do the first iteration of the loop. H is one because that's
its initial value here. Then H is going to keep
running until it's less than or equal to
what looks like five. And every iteration
we increase by one. For the first line, H is going to continue five times because that's
the size right here. If I step over that, we're
outputting one hyphen, then two hyphens, three or five. Then it's done. The very
first line on a pyramid, which is five units high, outputs five hyphens
on the right. Is that true? Is that right? No, because on the first line, it should output four. It's generating too
many hyphens here. Why is this? It's obviously
generating too many hyphens, but the hyphens on the left are generating the
correct amount. So you can see here,
the hyphen should stop when it's size minus y. That's the formula
we had in here. We've obviously done it
for this hyphen loop here, but we've neglected to replicate
the same functionality for the hyphens on the right
by using a break point. You can see that we
can examine the value of H while the
software is running. Let's just do that now. You can see we can
examine the values of H. We can examine
the values of size, We can examine the values of y. We can even examine
values up here, values coming into
the method using the step commands like
step over or into, we can actually control the
execution of the software. That's pretty cool, isn't it? Let's say we've figured
out the solution here, we've figured out the problem. Now, I mentioned a couple
of things before about run to cursor and run to
click. What are they? Well, run to cursor and run
to click short cut commands. Remember when I talked about dragging this yellow arrow here? Right up here so we can
control the execution? Manually run to click and run cursor short cuts for
controlling the code flow. Like code stepping. If I put
my cursor here, for example, right click and then I
choose run to cursor, click that and then the execution goes to
wherever my mouse cursor was. It's a bit of a short cut
and it's quite useful. Another one is run to click. You can see when every
time I click a new line, this mysterious little
green play button appears. But you can see here,
this one right here. I click this line, it
appears right here, it's like a bit
of a green ghost. So this is called run to click. If I click this little
green play button here, the code execution is going
to jump to this line. So it's pretty much the
same thing as clicking this line right Clicking
and choosing run to cursor. So it's just a nice
little handy shortcut. So you can see run
to click and run to cursor are both handy
little shortcuts. If this section of code
repeats multiple times, then I can click
this for example, and the code execution will then keep going until it
reaches this line. They're just nice little
code stepping shortcuts. This one is run to click
and the right click one, you can do run to code cursor, but there is a shortcut
for that as well, which is control F ten. The more you use visual studio, the more you're going to
learn these shortcuts. But every developer I know anyway will know step
into and step out, which is F 10.11 And those two are really useful for
stepping through code. So now we're going to run
the application and it looks like our issue with the
hyphens has been resolved. It was just a problem with
that last four loop here. And that's the upper bound. So when debugging
code in general, you have to ask yourself
a few questions. If an error occurred, what was the statement
or expression the program was doing at
the time of the error? What line of code did
your program fail at? Did the program fail? And you had that kind of highlighted line that said there was an error there.
What line was it? And when your program failed, what were the values
of the variables, like the parameters, the
local fields, any objects? What were those values
when the error occurred? What were the sequence of statements executed at
the time of the error? Were you inside a method? Of a method, for example? So, where were you? What
was executed beforehand? And I think I've pretty
much covered this one. What was the result of the
line of code where it failed? Or maybe the result of the
line of code before the error? So you have to consider
all of these things. You can't just put breakpoints anywhere and hope
to find an error. You have to kind of ask
yourself these questions. Kind of target the error
roughly where it might be, what class it might be in, what method it could be in. Then once you've isolated
it to a particular method, then you can start
kind of plotting breakpoints and
isolate it a bit. To summarize, this is
what debugging is. It's the process of
looking for errors, but if you have an error, it's the process of kind
of isolating the error. This is what a debugger is. So this is a visual
studio debugger. And you can use
this when you set your release mode to debug. And when you are debugging, you can place things
like breakpoints. And this is where the
code execution will halt. When the code execution halts, this is called break mode. You're entering break mode and
this is when a break point has been hit to control
the flow of execution. Using step in to step out, rent, to click renter, cursor, or even dragging the mouse
along this break point bar. Then this is called
code stepping. These are all the,
all the terminology to do with debugging
in visual studio. You may be surprised, but we've only scraped
the surface of debugging. I hope this tutorial helped
you. Thank you for watching.
55. 11-2. Immediate Window: In this tutorial, we're going to talk about the immediate window. Now this is a debugging utility and it is extremely useful. If you haven't seen
my last tutorial on debugging, breakpoints,
code stepping, then I highly recommend you watch that before
watching this tutorial, the immediate
window, what is it? If we come down here, you can see this little tab
here called Immediate Window. Maybe you've seen it before, maybe you've been wondering
what it's all about. If you don't see this tab here, then if we come up to the top, we can go to this
debug menu here. Now this is where all
the debug utilities and features live. If you were wondering, go to Windows and then
go to Immediate. And when you do that,
we come back down here and this little tab
should appear right here. Now, the immediate
window can be used at design time or run time,
so what does that mean? Well, design time is when
we're kind of developing. We haven't even hit the
green play button yet. We haven't compiled anything. We're not running anything. But what we can do,
we can actually work with our software
in design time, so the software is
not even running. So let's take a look
at this example now so I can show you
what I mean by that. If you followed our
earlier tutorials, we made a sample
calculator where we ask the user for a first number, a second number, and
then an operator. And then inside a method
here, for example, it takes those numbers
and an operator, for example, 54, and
then maybe plus. And then if the
operator is a plus, it adds them together and then just displays the result,
which would be nine. In this case, what we can do, we can actually test this method from the
immediate window. It's crazy, right?
The software is not even executing, it's
not even running. How do we do that? Let's
take this method here. Calculate, for example.
So I'll copy that. We'll come down to this
immediate window here. Now, anything in the
immediate window starts with a question mark
that pretty much says, okay, I want to run a command. So I want to run this method. So what I'm going to do
is call this method. I'm going to call it with five, and it takes a character, and remember characters
in single quotes. And we're going to do a plus when working in the
immediate window. The semicolon is optional. We can put it, we don't have to, it doesn't really matter. Now watch what happens
when I hit Er. It actually runs our software, compiles and runs it, and then gives us the
result for this method. You can see it actually
did this at design time. My software wasn't even running it gave me
the value nine. It's a pretty good way of
testing things like methods, evaluating expressions
at design time, but also run time as well. It can also do this while
the software is running. That's pretty clever, isn't it? If I put a break point, maybe here for example, let's clear the
immediate window, we can write, click
that and click Clear. All that will just clear
out the window for us. So now up here I
have a break point on double result
equals calculate. Before I even call the method, I'm halting the program, so nothing else is
going to continue. I run the application
by clicking the green play button or pressing five. It
doesn't matter. Now we're asking for the first
number five and then four, and then I want to
add those together. Now the program has
stopped executing. If I come down here, the bottom corner, I have this immediate
window right here. So I can do lots of things here. I can run that method again. For example, while
the code is running, One useful feature is
while the code is running, we have this Intellisense,
the Autocomplete. It's actually providing us all the variables in
scope, like number one. Number two, we can pass it
custom information if we want. If I say 54 and plus, just like we did before, then I hit Enter, we can
actually get the result. But you can see here, nothing
has really happened here. We can still continue
with this calculation. That's pretty cool, isn't it? What I can also do is
use existing variables. Right now I have number
one, number one. If I go over here and
highlight this value, you can see the user
gave the number five and number two
they gave four. And the operator they
used a plus right there. What we can actually do
is use those variables. We can actually see the result before the method
is even executed. Well, maybe I want
to multiply them. So you can see here five
multiply four is 20. So you can see the
immediate window can actually intercept
various things. Evaluate expressions,
run method, lots of things like that. All while the code is
actually in break mode. This method hasn't even
run yet, for example. Now there is one fine
detail with that. In this immediate
window down here, I've called the calculate
method twice now. But imagine if calculate
did something else, maybe it counted something
in the background. Every time I run calculate
it keeps a tally, a running total of how
many times I've called it. Now running this method in the immediate window
would affect the results. It's like this method
is actually being run now that could
cause various problems. So depending on what
your code does, if you mess around in the
immediate window here, it can affect the
results up here. It just really depends
what your code does. For something like
calculate, well, it doesn't really
store any information. It doesn't count anything. It doesn't keep a running total of how many times
it's been called. So it's pretty safe to run
in the immediate window. However, there are cases
where it would be unsafe, for example, for
those other reasons. That's just something
worth noting. So let me demonstrate that. Now just to illustrate
what I'm talking about. Let's say this calculate
method does keep a running tally of how many
times it's been called. But we use this running tally
for important purposes. Maybe something
else relies on it. This field is just going
to keep a tally of how many times the calculate
method is being called, when the calculate
method is called, I'm just going to increment this local field
by one each time. So if I run the application now, I'm just going to set a
break point on here so we can pause the execution
of the software. I'm going to type in
some sample figures, like five plus four. And then I'm going
to come over to the immediate window here. This hover over this
private field here. Numb times, you can see the
value is currently zero. But if I run this method
inside the immediate window, this maybe run it three times. By the way, by hitting the
up arrow on the keyboard, I can look through my previous
things I've typed in here. So that's pretty cool, isn't it? So I've run the calculate
method three times, but only from in the
immediate window. If I come up here and hover over my private variable here, you can see it has the value
of three things in your code are affected by anything you do in the immediate
window down here. So it is really important and it's something you
should be made aware of. Again, obviously,
everything resets when you run your application. But as far as debugging goes, it is worth noting this. So I've just talked
about the fact that when using the
immediate window, for example, to call methods, can change things in your code. Now this could be
wanted behavior, maybe you want to do this
and that's perfectly fine. But there are situations
like in our example previously where we increment
a variable, for example. But we need this in
here and we don't want anything in our immediate
window to change this. But we do still want to run the method from
the immediate window. Well, there is something we
can actually do to overcome this problem in the
immediate window where I call the method, whatever you put in here, whether it's calling a method, evaluating an expression, finding out the
value of a variable, you can just suffix it
with a little command called S E that stands
for no side effects. You can see when I type
that visual studio gives us some nice
indication right now. If I come up here, you can
see our variable here, number of times is zero. I come back down to
the immediate window and I press Enter. So you can see Calculate has
actually run the figures. It's added these
numbers together, but I've specified this
no side effects flag. If I come back over here and harver over
a number of times, it still retains the value
of zero by specifying SE, it means that no side effects
are going to happen as a result of you calling this method from the
immediate window. That's pretty cool, isn't it? That's one of the features
you can do with that. So we've called
methods with changes, we've called methods
without changes. Well, what else can we do
in the immediate window? Well, we can view
values of variables. So for example, number one. What is that? Oh,
number one is five. That's pretty cool, isn't it? So always prefix it
with a question mark. And obviously, these are
only variables in scope. So, for example, if these
variables don't have a value, or they haven't
been reached yet, or they haven't
been initialized, then obviously you can't
read the values of these. So it's only what's
called in scope, what we actually have access to. What we can also do is
evaluate expressions, for example, five plus
seven for example. It will give us the result and we can do that
with variables, so number one divided
by number two. It's pretty cool, especially
when you're debugging, you've put in some
sample numbers, but you can halt
the execution of the code and play around
with it in run time, rather than restarting
the application, Trying a few numbers, restarting it again,
trying more numbers. You can see how the
immediate window expedites that problem. You can just put in
whatever you want and maybe you're trying to
locate an error or an issue. It gives you a really fast, easy and dynamic way of trying to locate these
problems and errors. This is why the immediate window is pretty cool in that sense. But not only can we just call
methods and look at values, we can actually assign
values as well. If we looked at the value
of number one which the user entered is five
and they enter number two, which is there six. And the operator was a plus, so we're going to get 11. What we can do is actually
change values of variables. Rather than adding five
to six and getting 11, they're say number
one equals 11. Now number one equals 11. Let's make number two
equal 12 for example. And we'll leave the
operator as a plus. Now we've changed to
those two variables. Let's come up here now. If we hover over
those variables, you can see number one is now 11 and number two is now 12. We've modified the values
of these variables during break mode while the software is running at the
speed of light, like we were talking
about before, we've actually modified
things at run time. It's crazy, isn't
it? It's amazing. Now if I press five and continue with the
running of the software, you can see the result is 23. The user entered 5.6 but
we kind of went in there, modified some stuff, changed this one to 11 and
this one to 12. So you can see the
result is the reflection of the change that we did
in the immediate window. So that's pretty cool, isn't it? So imagine the immediate
window is like a little notepad
where you can play around and change
things and call things. That's the power of the
immediate window in visual studio when
working with C shop.
56. 11-3. Locals and Autos Windows: Continuing with our
topic on debugging, I'm going to talk about
the locals window and also the autos window.
What are they? Well, locals and autos
windows are only available during a
debugging session. We need to enter debug
mode and take a look at those windows and then I'll show you what they
have to offer for you. What I'm going to do now, I'm
going to add a breakpoint. Here's my simple calculator
application where I add, subtract or multiply
numbers together. So various things here. I'm just going to
set a breakpoint in here for no
particular reason. Then I'm going to run
the application in debug mode because we want
to do some debugging, the software is running, it's
asking me for two numbers. I'm just going to put some
sample data in there. Now, the code has paused, execution, and our break
point has been hit. Now the software
is frozen in time, and we can do whatever
we would like with it. If we come down here to
the bottom left corner, in my case, you can see we have some tabs
here, various tabs. One is called locals and one
is called Autos. Right here. If you don't see any of these, then come up here to the
debug menu, go to Windows. And then there's a
couple of options here called autos and locals. Now, you may not see
these menu options unless you're in a
debugging session. So make sure you're currently debugging and these
should appear. You can also use these
keyboard shortcuts as well, once you have these
windows visible down here. What these windows offer
is a real time look at the variables when we looked at the
immediate window before, where we could look at values of variables
with the question mark. Before we imagine this being a graphical user interface for the immediate window in terms of reading variables and objects
and things like that. Anyway, you can see I've paused the execution of the code
inside this calculate method. Here we already have
values for num one, num two, and also the operator. Our result is currently zero because we don't
have a value set. So if we look in this
locals window here, we can see all those values for those variables in
one easy window. So we can clearly
see what the user has given us and what
the result might be. Not only that, if we double
click the value here, we can actually change this
information in real time, just like before in
the immediate window, we can change these values. I go to result, I
can even modify the result before it's
even been initialized. And not only that change
the operator, for example, it doesn't only give
you a read only view, you can actually modify
these variables and the changes will be reflected during your debugging session. So that's pretty cool, isn't it? So we've looked at
the locals window here where we can view our variables here and also
change some of the values. Now these are available
in the current scope. So what that means is I've
set a break point here. We're inside this method, this is the current scope. We can access these
variables here, but we can't read anything
outside of this method. It's just things in
the local scope. What's local to us right here? This is what's reflected in
the local tab right here. Let's talk about the
autos window now and also how the autos window differs
from the locals window. They are quite similar
in the way they behave. You can change variable
values and things like that. You can view the value of
variables and objects, but why are they different? The autos window here, it displays information
on the current line. When I say the current line, the current break point, you see the software
is paused here, indicated by this yellow
highlighted part. We can see variables and
objects on this current line. Right here, we have the result. Not only that, we can view information on the
previous line as well. Now we can see num times, and if I step over
that using ten. So the code execution
goes to the next line, you can see the information is changed in our autos window. Really the main
difference between autos and locals is
that autos gives you the current line and
the one before it and locals gives you everything
in the current scope. You can see the locals
window here doesn't include non times because
we've defined it up here. So you can see it's a
static private field of our program class, so it's not appearing
in the locals window. The locals is only the
local things to you. The local things
in the scope and the autos is the current
line and the one before it. That is the main difference. But one thing I haven't
discussed yet is that both local windows and auto windows can
evaluate expressions. If I go to here, for example, where it says result, I can do what we did in
the immediate window before where we evaluated
certain things. I could say the result
is five plus four, so you can see the
result is nine. I can also use
existing variables. Number one, for example, plus 567 and that will get evaluated, so you can also
evaluate expressions in both the locals and
the autos windows. I've set up a sample
application here that uses some more
complicated objects. I have a video game
class that gets passed in some things
into the constructor. I have a list of users, and I'm adding three user
objects to that list, and also creating a
list of integers. So quite some complicated
things in here. I've put a breakpoint
at the very end. So we're going to enter
a debugging session, and then our breakpoint
is going to be hit, and then we're going to look at the locals window to see
what that might look like. I'm just going to
extend this up a little so we can see
a little better. You can see here, this is
pretty much everything here. Now I have these
arrows Look because these games are more
complicated objects. I can just click this arrow. I can actually see
all the properties and various things inside here. Now this little one
has a padlock on it, which means it's a
private field here. But this has a
little wrench on it, which means it's a property. I can modify the
values inside here, so you can see I can use a
text visualizer to view that, so I can look at the
values of the title. If I double click the value, I can modify various
things here. I could say that one's
for a Macintosh, just like before when we had simple variables,
simple value types. I could change the values. But even with complicated
objects like this, I can also change the values and view the hierarchy
of those as well. For this one right here, the user's list, I
can expand that. And then I can expand the
members inside there and see various names and ages
and things like that. So it's quite useful
and really powerful. During a debugging session, you can view the state
of all of your objects, whether they're complicated
or simple value types, or within one graphical
window right here. It really is amazing. And if we look at the autos tab, I said the auto tab
displays information on the current breakpoint and also the previously
executed line. In this case, we added a
breakpoint on this red line. The last statement that was
run was this line right here. Therefore, this object is made available in our autos window. If you have a really
large piece of software, perhaps with hundreds
or thousands of objects and variables
in the current scope, then you can actually
search for them too. So it's really quite
useful how that works. And you can specify
a search depth, which just means how many can arrows where your search
results may appear. So you can see there's a lot of depth options in there as well. But that is really the principle behind the locals
and auto windows. It allows you to view and
also change variables. But unlike the immediate
window over here, it gives you a nice graphical user interface to work with. And also gives you the state of what these objects are like, are these private fields, are these public properties. So it really is quite
useful in that regard.
57. 11-4. Watch Windows and Quick Watch: I'm going to talk
about watching now, and this is again related to
debugging in visual studio. What is watching specifically? I'm going to be talking
about quick watch and watch Windows.
So what are they? If you watch my other tutorial on locals and autos Windows, it kind of works very
similar to that. The only difference with a watch window is that we can choose what to add in there. But not only that, we can
evaluate expressions. So what does all that mean? Let's check it out. So right now I have a sample application, our little calculator
application. If you've been following
our other tutorials, I've just added a random
break point here. I'm in debug mode, I'm entering a debug session. The debugger is attached
to our software. It's asking for two numbers and an operator, five plus six. Now our break point
has been hit, the software is frozen. We can examine the
variables right now. We come down here we have
our familiar locals window, where we can look
at the value of the current variables
in the current scope. Number one is five,
number two is six, the operator is plus, and the result is 11. These are values of all the variables in the current scope. Now watch window. If we come up here to debug
and then go to window, and then you can
see there's watch 123.4 That means we can have up to four watch
Windows, four sessions. Let's talk about what a
watch session actually is. I'm going to click Watch One. And if we come down here, you can see there's a
Watch One tab which has been created
alongside locals, autos, and now we
have a Watch one. And you can see here it
says add item to watch. What does that mean? Well,
we can watch anything. We pretty much want to
like variables, objects. For example, if I come
up here to the code, we have these variables here. Number one is number two is six. If I right click number one, I can come down this menu
and click Add Watch. I'm going to do the exact
same thing for number two. Right click, Add Watch. If we come to the watch
window down here, we can see it works pretty
much like our locals window. We have the variables
we've added, we have the values, and also we can change the
values if we want to. You might ask yourself, why don't I just use
the local window? It does exactly the same thing. Pretty much the main
difference between the watch window and the
locals window is that watch, you can add whatever you want and also you can
add expressions. For example, I could say number one plus number
two and then hit Enter. I've added a custom
expression here. Now through the lifetime of my pretty much
debugging session, I know that the value of
num one plus num two, or I've put number one
there plus number two. If I can learn to type is 11. You can see I can put
expressions in here. I could say number one
multiplied by the result. I can put various
custom things in here. This is pretty much one
of the main differences between the watch window
and the locals window. What were those
watch 1234 windows. If we come up here to
debug again, then Windows, then watch and click Watch
to come back down here. Now we have another watch tab, then we can add other
variables here. Now these extra windows
are pretty much only useful when you have a
really large application. You want to isolate
certain variables from other variables just
so they're more organized and you
don't get confused. If you're working on maybe
a calculator application, you might want to put all
your watched variables in this watch window. Maybe the calculator
application has another feature that handles
something totally different. And then you put your
watch variables in here. You're organizing your
variables and expressions. You can have up to four
watch windows if you wish. That's one of the benefits and powers of the watch window. Not only you can view and change variables like the
local windows, but you can also add
expressions in here. That's pretty cool. You're not limited to just basic variables. You can even call methods. For example, I have a
method called calculate. And then I can calculate, say four plus eight for example. And then I can put that in there and that gets
evaluated as well. Expressions aren't just
tied to simple variables, but we can just put entire
method calls in here too. It's really powerful
and also really useful especially when debugging
quite large applications. And one thing I mentioned
at the start of this tutorial was Quick
watch. What is Quick Watch? Imagine you just want to watch one simple variable
very quickly. Say you just want to check out one variable's value real quick. That's pretty much the only
purpose of Quick Watch. If I write click number
one for instance, and click Quick Watch, or shift F nine,
this window appears. And when this window appears, you cannot continue debugging. You. Pretty much
just stuck in here. In here I'm quick watching
the variable number one, I can change its value, I can re evaluate
anything I wish. And I can also change or
enter any other expression. So I could say calculate. And it does have autocomplete
in here as well. So if I want to say five
plus four and hit Enter, I can do quick
expressions on the fly, but you get this kind
of annoying dialogue. And to be honest, I prefer just using the watch window because it does everything the
quick watch does. But I'm just
highlighting it 'cause I know some people
prefer to use that. I'm not sure personally why. But it is there if you need it. So that's essentially
the message I'm trying to get across. But the watch window does
everything quick watch does. So that's the powerful of
watch windows in C Sharp.
58. 12-1. The protected Access Modifier: I want to talk about the
last access modifier that we haven't
already discussed, and that is protected. We've talked about
public, private, internal, but now we're going
to talk about protected. Now, protected is a key
word which is generally used when you're inheriting
classes in C Sharp. So if you haven't seen
the tutorial I made on inheritance and
while we're at it, if you haven't seen
the tutorial I made on setting up multiple
projects in visual studio, then I highly recommend
you check those out first. Here we have a very
basic example. I have a main class here. It just sets up four
video game objects here. If we look at the
video game class here, not much is going on. It has one private field
and a constructor and it inherits from a main
game based class here. And it calls the games
constructor from here. Very simple, nothing we
haven't seen before. If we look at the base class, it has three private fields. It has a constructor, it has a sample public method, and a couple of sample
public properties here. Here we have lots of public
things going on here. Now, the protected keyword, it applies to methods like this one and properties as well. If something is
marked as protected, then it's only available to the current class, for example, game and anything descending from that, all of its children. Think of it. If you're like
the mother of a family, then you only want to share
protected things with your children or your
grandchildren for example. So think of it like that,
it's protected right now. This is a public method. Here. All it does, it gets the name and
join some strings together and the publisher,
right now, it's public. So we can access
this from anywhere. We can access it from
our main program. We can access it from video
game, no problem at all. What I'm going to do, I'm
going to make this protected, So you can see there's
the protected keyword. Now I've done that. If I instantiate
this class here, game from the main class here. Now the main class isn't a child of that class
then it's not going to. Let me do that, let
me prove that to you. Now you can see here when I
try and access the method, it's not even in
this list at all. And watch what happens if
I try to access it anyway, ignoring Visual
Studios autocomplete. If I hover over
that, it says it's inaccessible due to
its protection level. And that's because
it's protected. So it's only available from the current class or the
child classes of this class. For example, video game, Video game is a child class because we're
inheriting from there. If we just say base for example, then we're accessing the
base class which is game. Now we can see this
method, it's in the list, and when we try and access that, there's no errors at all. That's the power of the
protected keyword in C sharp. But there's a couple of combinations that can
actually go with protected, and that is protected internal, and also protected private, protected private, and
protected internal. These are a couple of
combinations we can use when dealing with the
protected access modifier. So we can basically double
up access modifiers, but only when using protected. You can see here
we can use it in three combinations by itself, which is what we've
already discussed. It's available in
the same class. Methods and properties
are available in the same class or
any of its children. We've discussed that
next, protected private. If something is marked
as protected or private, a method or a property, then it can be accessed
in the same assembly, but also from within
the same derived class. If our game class here
is in the same project, the same assembly as our child, which would be video game. If these exist in
the same project, the same assembly, then we can
make use of those methods. However, if this game file here was in a different project, then we cannot access the
methods and properties from this child class that
is private protected. So let me show you
an example of that. Now I'm going to mark Publisher. This is a shop property here. Publisher, I'm going to
market as private protected. Now if this class exists outside
of the calling assembly, wherever we want to use this, it's not going to work. Let's have a look at an
example of this working. We can say publisher. We can access this, no problem. If I just say string
something equals publisher, there's no problem
because we can access it. Now let me move this class here. Public class, main, outside
of the current assembly. If you saw my tutorial
on multiple projects, you'll probably know
how to do this. If we come over here to
the right hand side, we get our game class. The parent class, I'm
just going to drag and drop into the second
project I have set up. The principle is I
just don't want it in this project anymore now,
I'm going to delete it. Now game is in this totally
different project over here. Now game is in a totally
different assembly over here. We can come back to our
video game class here, which is in the other assembly. Go over here now you can
see an error has occurred. So it can still find game because we're referring
the other projects, so it knows where it is. You can see we're
inheriting from there. However, now a red
line has appeared. And if you hover over that, it says publisher is inaccessible due to
its protection level. That is because we've made
it private protected. If something is
private protected, it has to be within
the same assembly, so the same project. And it has to be a descendant of this class that is
protected private. Now we understand
protected private, the same assembly and a child, it's very easy to explain
what protected internal is. That it can be a, any descendant of the class, but it can be in
any other assembly. It doesn't matter where, for example, base
class is located. It could be in a totally
different project. But as long as it's
protected internal, we should be able to access it. Right now, we have this error because of protection level, because video game and game
are in different assemblies. I go back to game, I now make this property here, protected, internal or
internal protected. So I've set that up there
I go back to video game, and now you can see the
error has gone away. So that is the difference
between private protected and
internal protected. It just means the
base class has to be either in the same assembly
or not in the same assembly. So those are the three
access modifier types when dealing with protected, so the base class
and its children. And then we can
double it up with private or internal depending on if the base class is in the same assembly or
a different assembly. So that is the protected
access modifier in shop.
59. 12-2. The static Keyword: Now I'm going to talk
about the static keyword. You may have seen
this if you've been following our other tutorials. This little keyword here called static, what
does that mean? What does it do? And
why should we use it? Let's take a look at
this example here. I'm just defining four
video game objects here and calling the constructor
with three parameters. If I look inside the
video game class, it just has three
private fields. Here's the constructor that
sets the private fields. I just have an example method here that returns the title. And just an example
property here that just gets the publisher very basic. If I have a class like
this, for example, how would I perhaps keep a tally of the number of video games
I have in my collection? This is just an
example what I could do every time I instantiate
the video game class. I could keep track of a counter. This counter can keep a tally of how many video games I have. In my collection, I
initialize a counter to zero. Every time I create
a video game, I can increment the
counter by one. I could do something
like this, for example. That would work perfectly fine. But it doesn't look
very elegant, does it? Not only that, but it
doesn't really follow the principles of
abstraction very well. We'd like to keep
this counter maybe hidden away in the video
game class, for example. How would we achieve this? How could we do
this if we set up a counter inside this video game class,
for example, here. Then in the constructor
for that class, I increment the counter by one. However, the problem is this counter will belong
to each instance. So if I go over here and from game one I can
access the counter, but it's only going to have
a value of one because the counter belongs to
each separate instance. So how do I have like
a global counter, something inside this video
game that keeps track of the number of instances of
this class that we create. Now this is where the
static keyword comes in. When we use the static keyword, we can use it on constructors, we can use it on fields, we can use it on methods, and we can even use it
on the whole class. For example, for example, if I define this counter
field as static, then this field will be
shared across all of the instances which have been
created from this class. It's a class level field. Anything with static inside
the class will belong at class level and not
instance level like here. For example. Let's take a
look at an example of this. Every time I create a
new video game here, I want inside my constructor here to have a counter
that increments by one. This will keep a
tally of the number of video games in
our collection. For example, what I could do, I can just do a sample
line here that writes to the console how many video games we have in our collection. Every time I construct a new object of the
video game class, I'm incrementing the counter, which is static, it's at
class level by one each time. Then I'm outputting a message to the console window that just expresses how many
games I have in my collection when
I run this program. Every time. This is constructed here because we're
creating a new instance, the counter is going to
increment by one each time. Let's take a look at that
Now you can see here, it's incrementing
by one every time this counter is being shared
by all of these instances. Here, it's quite clever how
the static keyword works. What we can also
do, for example, is have a static method as well. For example, I can create a static method that gets
the result of my counter. Let's take a look at
that. Instead, I'm going to remove this line here. For now, I'm going to
create a static method. What this method does, it
just returns the counter. And it's a class level method, that means we access it from the class and not an instance. Let's take a look
at that right now. If I go into the
main program here, if I go to game one, for example, now game
one is an instance. This method will not
appear in this list. You can see there's no
get counter method here. That's because it's
a class level. In this case, I would have to type in the name of the class. Then once I put a dot after
the name of the class, these are all the class
level members right here. So you can see this method
here called get counter. It's a class level,
not instance level. And now we can get the number of video games in our
collection, like so. If we wish to output
that to the console, we can just copy
that method here, put it right here, and then
delete that semi colon. Now I'm going to run
the application. You can see we have
a similar result. It's just getting
the grand total of the number of the video
games in my collection. And I appreciate I've just spelt collection wrong, but
nobody's perfect. That is an example
of a static method and also a static
field in C Sharp. Perhaps this static keyword
that we've been seeing in all of our tutorials so far
is starting to make sense. Now our main class here
is called program. By default, there's a method
called main which is static. This main is a
class level method. By default it's the
first method that gets executed when
the program is run. If I create a new method here, for example, I've just created
a method just like this. I attempt to call this
method from main. This is a static method. This is not a static method. Watch what happens. So you can see there's a red line here. If I hover over that, it says the object
reference is required for the non static field or
property program test. That's because we're calling a non static method from a static method
which is not allowed. If something is not static then it is an instance
level method. Because we're inside
a static method. Here, there's no
instance to operate on, we haven't created an instance, We're not within a
method of an instance. There's nothing to do with
instances going on here. We're inside a static method, but we're trying to call
an instance level method. It's not going to work. In cases like this, you would
have to create an instance. This is just an example. Anyway, I wouldn't
recommend you create an instance of the
program class, but it just helps my
explanation here. Once I put the instance before this instance
level method, you can see the error has
been resolved because anything that's not static
should belong to an instance, it's a instance level. What we could also do instead of that is just mock this
method as static. That way we're calling
a static method test from another static
method is perfectly fine. One other thing we can do with the static keyword is to mark
an entire class as static. What we do, we take
the static keyword and put it next to the
class definition right at the top here. When you do this, everything inside the class here
must also be static. Because if you define
this at class level, then it implies that everything
within must be static. This is why all these
errors are appearing here. But the main important
thing about marking a class's static
is that we cannot create instances
of static classes. They are abstract and
sealed implicitly. If you remember an
abstract class, you can't create
an instance of it. And if you remember
a sealed class, you cannot inherit from it. So this is implicit, this is why we have
all these errors here when creating
a new instance, so we can no longer do this. Let's take a look at turning this class into a
purely static class. Strap in and buckle
up. Let's go. All of these private
fields must be static. Now our constructor
in a static class, it must be static. But static constructors
cannot have access modifiers. We cannot have public there. Also, it can't have parameters. Let's remove those two also. This keyword is irrelevant
because this is only to do with instances
that has to go too. Now, all our methods and
properties must also be static, and that should about do it. This is an example of a
static class right here. Now you may be wondering, well, if I can't instantiate
this class, then how is this
constructor even called, for example, what's
going on here? Well, by default, when you run the application and
access this class, this constructor is executed by the run time
environment once. This will get executed
automatically one time. Anything in here in
the constructor, the static constructor should initialize any variables or
anything you want to do. That's the purpose of
a static constructor in a static class. Now, if we come over
to our main file here, you can see we can't create instances of the static class. We can only access
things at class level. Now, I've marked everything
as static, The properties, the methods, this is how we pretty much
refer to the class. We put the class name like
before and then a dot. Then we can access
various things here. And now, because there's no
instances for this class, all of these members will exist one time because that's
the point of static. We can set a publisher
and access that. Also, we can get our
video game count like we were doing
before. It's no problem. Just to prove that the
constructor is run once, check out this method
here where I get the counter for the number
of video games I have. I'm just going to duplicate this method, so
it's called twice. I'm going to put two
breakpoints on here. The code stops when
this line is hit and then going to go inside the constructor and put
a break point there. I'm now going to run
the application, so you can see what happens. Now the constructor
hasn't executed, but the break is
on this line here. Video game dot get counter. If I step over this, you can see the constructor
here is called. If I step over that, we get the counter, we
go to the next line. If I step over that, you can see nothing happens. The constructor is only called once on this first line here, and it's ignored on
subsequent calls to any methods that
exist at class level. I hope this made sense. It's quite a lot to take in, but this is the point of
the static keywords to put pretty much anything
you want at class level, the concept of instances in this case are pretty much
ignored In that respect. I gave you an example of how static constructors also work. The constructor is called
automatically just when you touch any
method or member, and then it's ignored for
any subsequent calls. After that, I hope
this helps you. This is the power of the
static keyword in shop.
60. 13-1. The readonly Keyword: In this tutorial, we're
going to be looking at the read only
keyword in C Sharp. Now what does the
read only keyword do? Well, the read only
keyword is what's called an immutable data type.
What does that mean? It means once you
have a value set inside a variable or
a field for example, then you cannot modify that
value once it's been set. What does all that mean and what other conditions are
involved in that process? Let's take a look
at a small example. Here I have a class called Dog Dog has a constructor that takes one
argument called breed, which is the breed of the dog. Like a terrier or a
Chihuahua for example. I have two private fields
right here breed and another one representing
just a unique ID for every dog we construct. And then I have one public
property that gets and also sets the breed of the dog with the knowledge
we've gained so far. If we want users
to be able to say, get the value of the breed, but not set the value we want
to make it read only then. If we have a property
like this, for example, that exposes this
private field here, then we would simply just remove this set
clause right here. When we try to actually put
information into the breed, it's not going to letters. So if I go dog breed and
then try to give it a value, it doesn't really matter what we put in here. We have an error. If we harver over
that, it says it cannot be assigned
to, it is read only. That is one example
on how to make say, a property read only in C Sharp. But wait. At the start
of the tutorial, you talked about fields and variables and
things like that. How do I do that using
the read only keyword? Well, let's take a look. Let's go back into
the dog class. Now what I'm going to do is
use the read only keyword. I'm going to undo
these changes and put this set clause
back in here. So we're now setting the value, but now I'm going to mark
this field here as read. Only once I've done that, you can see an error
has occurred here. It's not actually letting me
use the set clause anymore. If I hover over that, it says a read only field
cannot be assigned to, then there's a little
condition here, except in a constructor we can assign it inside
a constructor like here and except it only setter of the type in which the field is defined or
a variable initializer. What does all that mean? It's basically saying when you
use the read only keyword, you can define it once. For example, we could define it here and initialize it here. Let's just say every new dog
is a Chihuahua, for example. It's no problem at all. We're actually setting it, but we're doing it
when we declare it. We declare the variable here, but we're also initializing
it that is allowed. The other thing we
can also do is set it inside a constructor
like inside dog. And we can do this
multiple times. As long as it's inside a
constructor, it's okay. We can do it 1,000
times if we want to, but we cannot set this inside, for example, this property here. We cannot say, create a
brand new method and set it here, for example. This isn't going to work. You see the point here. Even if we access this
from outside of our class, I just make this lower case. Now to access the field, you can see it cannot be assigned to accepting
a constructor. So that's the power of
the read only keyword. And there are a
couple of reasons you might want to use these when working with
immutable data types like the read only keyword. You want to use these for things that maybe you want
to set up one time, but then you'd never want to
modify the value of this. This is because, for example, if I generate a unique
dog ID, for example, I only do this once, but then I don't want
this ID to change because each dog has a unique
ID associated with it. If I start changing ID's
of dogs, then for example, if we have a bit of
software that tracks dogs, you know the dogs
that wear the collar. And if the dog gets lost, so they can scan the
collar or the microchip. And then it uses the ID from
that to reference maybe a database and find out where who the owner
of the dog is. Perhaps, don't make this
read only then we might have a property or someone calling this application might accidentally change the ID, which could be disastrous. This is why immutable data
types are generally used. We want to prevent
fellow developers, or even users of the software, from modifying these values. But for something like an ID, where we generate a unique ID
for each dog in our system, it's very important that we make fields like these read only. So it really depends entirely on your system
what you want to do. But it's really good
practice to say, if you have variables or fields which you do not want
the users to modify, then always make these
read only for example. So that's one way you
could handle this problem. Another condition to do
with the read only keyword, for example, it can
only be used on fields. Now remember, fields are
what are defined in classes, just underneath the
class declaration. If I go into my A main program here and use it inside a method. If I define this
inside a method, obviously removing private, then you can see
there's a problem. If I hover over it, it says the modifier read only is not valid for this item. That's basically saying, okay, you cannot use the keyword
read only inside a method, but we can use it
at class level. For example, we can use it here and it's no problem at all. That will work just fine. But we cannot use
this inside methods. There is a different keyword we could perhaps use for that, and that is the constant keyword which we will be
talking about as well. The last thing I want to
talk about to do with read only is when we
can set the value. We can set the value
at compile time, which means we can
give it a value in our development mode when
the software compiles, that's when the check is done. I can give a value to red, here, I can say Chihuahua and
there's no problem. This is at compile time. Again, inside the constructor, we're setting this value. However, we can also
change the value at run time when the
software is run. However, we can also initialize a read only field during run time when our software
is actually running. When we construct this
dog object right here, the constructor
is getting called and then this line
of code is executed. And this happens during run time when our
software is running. If I run the software, you can see it sets that
value in the constructor. There's no errors
and it's no problem. We can set a read only field at compile time and at run
time, two different places. But that is the read
only keyword in C Sharp and why you should use it
and also how you can use it.
61. 13-2. The const Keyword: I'm going to be talking about the constant keyword in C sharp. It looks something like
this. What is this? Well, the constant keyword is another immutable data type. If you watched my tutorial
on the read only keyword, then understanding
the constant keyword is going to be a lot easier. In this tutorial,
I'm going to be explaining the constant keyword, but also demonstrate
the differences between constant
and read only as a lot of people get
confused between the two and which ones
they should use and when. Let's take a look at
the constant keyword. Now what I'm going to do is
use the previous example. This will help illustrate
the difference a lot better. So here I have my dog class for anyone that didn't watch
the last tutorial. I have two fields here, a constructor that
sets these up and one property right here that just gets the value
of the breed. So it's a simple dog class. What I'm going to do is modify
this private field here, which is currently read only, and change this into a constant. Then I'm going to demonstrate the behavior and the
differences in this case. So remember with a read
only field right here, we can actually
set the value from a constructor and we
can also initialize it. Let me change this
into a constant now. Now you can see an
error has appeared. If I hover over the
error right here, it's saying a Guid type cannot
be declared as a constant. Certain data types
cannot be constant. That's a bit of a problem. Okay, let's make
our ID an integer. Instead, we'll have some system that generates a unique
integer for each unique dog. Okay, no problem. We'll
use a different data type. Now there's another problem. If I hover over
this, you can see a constant field requires
a value to be provided. Basically, that means when you declare a constant
like we're doing here, you have to initialize it, you have to give it a value
all on one line right here. Otherwise, it's not possible. When we declare
something as a constant, we have to give it a value. Let's just say 456, for example. Now there's another
problem down here. If I haror over that, you can see, well the error
message isn't very clear. But basically once you declare a constant and initialize
a value into it, you can then no longer modify this field or variable
from anywhere else. Not in a constructor. You cannot modify
it from a property. You cannot modify
this value from outside of the class
anywhere else. Once a constant has been
set and initialized, which you both have
to do on one line, you cannot modify this value. So think of the constant keyword as more like a stronger read only with a lot more limitations in terms of modifying your data. This is a real big difference here for something like
generating a unique ID for a dog, read only as a good
keyword for this, because we can initialize
it from the constructor. However, generating a unique ID for a dog with a
constant keyword, this would be a very
bad way to handle this situation because const wouldn't be a good way
to represent this. You may be asking, well,
what can I use const for? What is a good example of
using this constant keyword? It seems quite limiting and it seems like I can't
really do much with it. Well, for example, let's
say we work with I. When I say pie, I don't
mean an apple pie. I mean pie R squared 3.1 419. I think pie is accessed
in the math static class. We've looked at the
math static class before when working with
numbers previously. And there's lots of things
you can do in here. But you can see in here, there's one called pie. If I hover over that, you can see pie is a
constant, 3.1 4159. I was close, I was close. Pie is a constant. And that's because
pie doesn't change. Pie is always 3.14 159265. It just is that value. There's no reason
that I can ever think of where we would want to
modify the value of pi, because pi is what it is. Pi is pi. It's the relationship of the radius to
the circumference. Now, I'm not a mathematician, but hopefully I put
the point across that you would never
need to modify pi because it is a set value. This is a very good example
of using a constant. In this case, pi is constant. You don't modify pi.
It is what it is. And when you try to, you can
see there's a problem here. So pi is a very good example of where you would
use a constant, because this value, once set, is never changed and
there's lots of them. Look, there's pi
there and towel. I've never heard of towel, but oh, it's to
do with radiance. Okay. Here, a distant memory
of a very early math lesson. So you can see this is the
point of using constant. It's where you would never
want to change the value. And once it's set,
it's set now constant, You set this at compile
time, not run time. When your application
is running constant, variables or fields need values. You can remove the value, run the application, and assign it while the
software is running. This only happens
at compile Time. Another thing with constant, unlike read only
read only you use it on private fields of classes like we
explained previously. However, with Constant we can use these as private
fields of the class, but we can also use
them inside methods. For example, I can just declare a variable here I call it ID, I give it the value,
then I can use it in the remainder of
my method right here. I could also pass it to another
method, it's no problem. Constant variables,
you can set and declare and initialize and
then pass them around methods, it's no problem at all. However, if this was read only
like we showed previously, it's not possible because read only is restricted
to private fields. One other thing I'm going to mention about the
constant keyword is that it's implicitly
static by default. Basically that means
it's static by default. If you watch my
previous tutoril where we talked about the
static keyword, you'll remember that
static is a class level. This is where we create
a new instance of dog. Then using the instance
which we've created, we can access instance level, fields, methods, properties. But when we access
things at class level, we use the name of the class, then access anything
at class level. Things at class
level are static, Just like the constant here. What I'm going to do,
I'm going to make this constant ID public. That means we can access it
from outside of the class. I go back outside
here, I put a dot. Now you can see the ID is here. This is because fields
which are marked as constant are implicitly
static, static. If I use DG the instance
at instance level, you see the ID is not here. It's not here at all. But at class level,
this is where it lives. This is because
anything defined as a constant is implicitly static. It's available at class level. You can see it's not static
at all, it's just constant. That's because this has a
value and wouldn't set. We can't modify it. Why would we want
every instance to have a bit of area in memory
where this ID is defined? It doesn't really make sense. If you have 1,000
dogs in your system, then some of your memory will
have to be available to add this constant ID for each
dog in your software. Now, this doesn't make sense
because once it's set, it's set, that's it. So it makes sense really to have this available
to the class. So if we have 1,000 dog
instances in our system, we don't have 1,000 copies of a variable that
cannot be modified. So that is the reason
for this and it sort of makes sense when you
think of it that way. That's really a bit of a gotcha to do with constant fields, is that they're at class level. I hope in this tutorial I've highlighted what the
constant keyword does, what it means, and
more importantly, the difference between constants and read only in C sharp.
62. 14-1. Stack and Heap Memory: When developing
applications with C Sharp and Visual Studio, and you're creating things
like variables like integers, boolenes, maybe
instances of classes, objects, arrays, and
things like that. It's important to
understand what is happening with those
in the computer's memory. What if I told you this? Depending on what data
type you chose for your variables determines where and how this is
stored in memory. What do I mean by that? If you use an integer
variable or a bolen variable, or a double for example, then these are
stored and accessed very differently from
different data types. And when I say
different data types, I mean things like strings, arrays, and custom objects. But why is that important? Well, there's a couple
of reasons why you might want to learn about
stack and heap memory. One, for performance, your
application can run and function a lot faster when you
understand these concepts. But not only that, but what if I told you that, for example, if you pass an object
into a method, you could potentially lose data or overwrite existing data. What would you think about that? Now these are two
of the many reasons to learn about stack
and heap memory, and this is the purpose of
this tutorial right now. Now from experience,
and believe me, your average developer
won't have much knowledge on what's happening in
memory with these variables. However, just having a
tiny bit of knowledge on this will let you stand
out from the rest of them. So let's talk about stack
memory for a moment. The architecture of
stack memory is kind of like a stack of pizzas
or something like that. You keep adding
pizzas to the stack, one on top of another, and then remove
them sequentially. So the top one first, followed by the next
one you can't access, for example, pizzas
in random orders. It has to be added to the stack. So added to the stack of pizzas
or removed from the top. So this is how
stack memory works. It's sequential, so you add things to the top and
you remove from the top, we keep short lived
items on the stack. Now what is a short lived item? Well, these are generally
called value types. Things like integers, Boo
leans characters, floats, doubles, things that
are kind of quick, simple things which are
considered not complex. Simple data types like those, not things like complex objects. And when we store things in stack memory, it's
retrieved fast. It's a very fast area of memory, just from the way it's
architectured sequentially. Now, the heap area of
memory is quite different. Imagine that stack of pizzas, but instead of a nice
organized stack, throw them all on the floor, so there's pizzas
everywhere in heap memory, there's no ordering of the
items in the memory per se. However, because of the
natural layout of items in the heap memory
retrieval is slower because the process is more complicated on
accessing the data. Therefore, it's considered
slower than stack memory. Generally, you keep
long lived items on the heap, so complex objects, but also things that will be made available for a long time, for a long duration of the
running of your application, whereas things on the stack would be considered short lived. So maybe a quick calculation
like four plus four, for example, what kinds of data types and items are stored in the heap
area of memory? It's things like
objects, classes. When we instantiate a class, strings, strings
can be huge items, arrays, anything
which is global, globally available throughout
your whole application. For example, even though a simple integer is
considered a value type. However, if you made this global like static or
something like that, and it's made available to
every class in the system, then this is where
the rules change. This would be stored in
the heap area of memory because it needs to be
made available for longer, so long lived items in the heap. Things like strings, classes, as are all considered reference types,
that's the key word. You may hear a lot in the
future when you create a new reference type which is stored in the heap
area of memory. What also happens
is that something called a pointer is
created on the stack. So what happens
is the pointer on the stack points to an area of the heap memory where
your object data lives. When you create a reference type like an array, for example, a pointer is added
to the stack and the actual meat of the
operation is added to the heap. The piece of information on
the stack pretty much says, okay, you can find it right here at this memory
location on the heap. That is the only thing
that gets added to the stack when you
create a reference type, like something complicated,
like an array, for example. This is where the
name reference type comes from because we're referring from the stack to the heap where the
data canner lives. And this is why things like
integers, Boulen, shahs, simple types are called value
types because the value is directly stored in the
stack area of memory. Now I appreciate that this is quite a lot to
understand and take in, but don't worry
about understanding every single thing I've
outlined in this tutorial. The main takeaway is to
know and understand that certain data types are stored in the stack
area of memory. And the stack area of memory has its own characteristics
and benefits, and other data types
are stored on the heap, again, with its own characteristics
and things like that. In the next couple of tutorials, I'll be using some examples so you can further
understand this. So don't worry about understanding
everything right now, but right now I'm
going to talk about something called
a stack overflow. Now, you may have heard of
the website stack overflow, or maybe you've heard
of the term before. It doesn't really matter if
you've heard of it or not, but what we're going
to do is intentionally cause a stack
overflow in C Sharp. And I think it will be quite
a fun example to simulate, because I can show you that stack memory has
size limitation. And this is why large
complicated objects are stored on the heap. So let's try and overflow
the stack area of memory. Now with a quick example. I'm over here in visual studio. Now I have a very
simple application from the main method. Here we're calling
an overflow method. And the overflow method is just writing hello to
the console window. So not much is going on here. Now an easy way to cause a stack overflow is to
have a method call itself. You may be asking yourself
the following question, how does this cause
a stack overflow? I'm not defining any integers, Booleans, anything like that. What is actually
overflowing the stack? Well, when you call a method, the method reference is
also added to the stack. This is another example
of stack memory. So we can achieve a stack
overflow like this as well. Similarly, we can create
a few million variables, the integers, perhaps
that would work too. Maybe there's lots of
ways to accomplish this, but this is a quick example of a very easy way to do this. So I'm going to run
the application now and we're going
to see what happens. I run the application, it pretty much crashes out. It says in visual studio,
stack overflow exception. When I look at the
console window here, you can see it says
stack overflow repeated 24,109 times before the stack is completely full and
it started overflowing. If we look at this diagram here, you can see how the stack
and heap memory grow, but the stack memory is limited. The point of the stack
memory is to store actual values for data
types like integers. It'll actually
store, for example, 15 on the stack, rather than if we have a big reference type like an array, then this is stored
on the heap because these can grow very, very large. However, with the stack area
of memory, it's limited. It's finite. You can only put
so much information here. And as you can see here, we can store a reference to
our method call 24,109 times. So that is how limited it is and this is why everything
isn't stored on the stack. Yes, the stack is fast, but its space is limited. The heap is slower, but it's a lot larger. So you see this pros
and cons of each, and this is why
both of these exist and also why it's important
to understand both. So I want to talk
about one more thing, and that's the call stack. What is the call stack? If I come back into visual
studio here and scroll down, you can see there's
a little window here called called stack. If you don't see this window, then come up to the top, go to bug, then windows, and then call stack. And this should appear at
the bottom right here. What the call stack does, it gives you a visual
representation of your method
calls, for example. So you can see here we
started with the main method. Here we called overflow, and we repeated this 24,106 times before finally
ending in a stack overflow. It gives you a nice
visual representation of your method calls. And you can see the architecture
here is pretty much like the pizza example I
was talking about earlier, with the first call
being the bottom pizza. And these are slowly
added onto the stack. But the reason I'm talking about the call stack right now is
that beginner developers, can I get a little
bit confused between stack memory and the call stack? The call stack gives you a
nice visual representation of your method calls. But it's not stack memory. This isn't what you
see in stack memory. The call stack doesn't
show you your variables and assignments and
things like that. It only gives you
like the method calls while they are
loosely related, the call stack is
not stack memory. I can illustrate that now with a better example
of the call stack. Take a look at
this example here. It's quite simple. The main
method here calls method one. Method one calls method 22, calls 33 calls four. Finally, in four, we just say hello to the console window. It's very simple, but this
example will show you how the call stack works and how these method references get
added into stack memory. Basically, the
stack architecture, the pizza architecture. Let's have a look at an example. Right now, I've added a break point here on
the very first line. So we're going to
enter break mode as soon as this is hit. So I'm going to compile and
run the application now, now we're in break mode here. If I just bring this window
up with the call stack, you can see one item has been added to the call
stack which is main. Now I'm going to step into this by pressing 11 on the keyboard. Now you can see I'm
inside method one. Now this has been added
to the call stack here. This is our first
pizza in our stack. This is our second pizza. Now, I'm going to
press F 11 again. Now we have our
third pizza on top. I'm going to step
into this again. We have our fourth pizza. You can see how this works. So the call stack gives you
a nice visual representation of where you are in your application during
a debugging session. It's semi interactive as well. You can double click these and
you can see where you are, where this method
was called from, which is really helpful when
you have multiple files, solutions, projects,
things like that. It can navigate you directly to where
this was called from. But this is a similar
representation to how stack memory works. We have our first value here, then they get stacked on, and then they get popped
off in order like this. They cannot be
accessed at random. So it's like first
in, first out, which is the terminology there, stack memory and the call stack use the stack architecture. And while they're related, they're not exactly
the same thing. I hope that makes sense. Now if I then go to method four, you can see that's the last one added onto the call stack. And then I step over that, and now you can see they're slowly getting popped
off the stack. The method three will
be the next one to pop off because we're
just coming out of there. Then two, then one. Now we're back in
the main method. You can see it's the last item remaining in the call stack. So that's what the
core stack is, and that's also what
stack architecture is. And you'll see
stack architecture in many different
programming languages, but it's not limited
to programming either. One last thing I'm going to
talk about is a key word you may hear in the future
called garbage collection. So what is garbage collection? Well, when I talked about creating reference
types, for example, things that are stored in
the heap area of memory, like classes,
instances of classes, strings, arrays, and
things like that. I also said that a
pointer is created on the stack and this points to
the information on the heap. It's like a pointer.
What can happen is the pointer is removed from
the stack area of memory, but the actual data is
left behind on the heap. Now, our application has no idea where this
information is anymore. Maybe it doesn't even
need the data anymore. But it could still exist in
the heap area of memory. But because the
pointer is no longer pointing to it in the
stack area of memory, this data on the
heap is useless. It can't be used,
it can't be found. It can just fill up your memory until
there's no memory left. This is quite a big problem. This is usually referred
to as a memory leak. So there's something
called garbage collection that actually kind of
goes through the heap. Area of memory, works out if there's a pointer pointing
to it on the stack, and if not, it removes, it frees up the memory. And this is what garbage
collection does. And in a language like C shop, you don't have to worry
about garbage collection. But I thought it'd
be an interesting bit of trivia to tell you. But if you work with
other languages, perhaps like C plus plus, then you do need to worry
about garbage collection. So maybe it's
something to consider, but it is nice to know. And when your application
closes or terminates, then generally the
memory is freed up.
63. 14-2. Method Parameters - Passing by Value: Before watching this tutorial, I highly recommend you watch the previous tutorial on
stack and heap memory. Otherwise, this might not
make a whole bunch of sense unless you're familiar
with stack and heap memory. Now let's take a look
at this example. Here we're looking
at some method passing now passing some
parameters into a method. Then we're going to
modify some values. Just consider this example
here. It's quite simple. In the main method of
the application here, I'm defining two value
type variables here. Now these are stored
in the stack, the stack area of memory,
they're value types. Then I'm outputting the values for these variables to
the console window. I'm then calling a
method called reset. And I'm passing both of these value type variables
into this method right here, I'm resetting these
variables which are being passed into zero and then I'm outputting them to
the console window. Once the method is finished, executing control is
passed back up here. And then I'm outputting the values of these
variables again. And then I'm keeping the
console window open. Question, what do you
think the output would be? Well, let's take a look at
what the output actually is. I'm going to run
the program now. The value of num one is the
value of num two is four. And then the value inside the method is zero because
we're resetting them. And then after the method is run 6.4 is that what you expected? Perhaps so, but now look
at this other example. Let's take a look at
this example here. It's very similar to
the previous example, but instead of using a simple
value type like an integer, we're using a reference type. And reference types, like
we talked about before, are stored in the heap
area of the memory, and a pointer to that data
is stored on the stack. What we're doing,
we're instantiating a video game object. If I go to the video game class, you can see it's quite simple. It has one private
field here called title and one public
property called title, which controls getting and
setting of this field here. Very simple. We're setting the title for the
video game here, a World of Warcraft, and then we're outputting
it to the window. We're getting the title
before a method is called. Now we're changing
the title here. In this method, it takes in a video game object and then we're outputting
something to the window. We're outputting it to the
window inside the method. But before we change the title of the game inside this method, we're changing the game title to change something different. Then after the method
is finished executing, we're outputting the
game title again. Now what do you think
will happen this time? Okay, let's take a
look at the result. If I run the application, you can see here the game title before the method is
World of Warcraft. The game title inside the
method is World of Warcraft. Remember inside the method, this is before the
change has taken place, but after the method
has finished executing, we come back to Maine
and output this. Here however, you can
see it's retaining the value which we changed it to inside the
method. Why is this? Why are these changes being
persisted from changes inside methods for reference
types but not value types? What is going on here? Well, allow me to explain. I'm coming back to
the previous example now where we had two
simple value types here, two integers, and we passed
them into a method here. Now in C Sharp, when
passing objects, whether they're value types or reference types as
parameters to methods, by default, these
are passed as value. They are passed by value, unless explicitly noted, they should be
passed by reference. We're going to talk about
passing by reference later. But consider the default which is getting passed by value here. What does passing by value mean? Well, by default, when you call a method and pass in these
two parameters here, a copy, a copy of
this data is created. Here we have a value of six in number one and a value
of four in number two. We're calling this method here. Inside this method, it receives a copy of
these variables. It's not pointing to the same
area as memory of these. These are literally copied. Then the method
actually works with a duplicate copy of
these variables. This is what it means when
being passed by value. Any work we do
inside this method here is done with a copy
of these variables. And when the method has finished executing and control
is returned here, we lose everything inside
here because this is a duplicate copy and it only
exists within the method. Once the method is finished, we have no knowledge
of this unless we specifically return
something out of here. That is an example of
passing a value type into a method and it's
being passed by value, it doesn't affect anything
outside of the method. Coming back to our other
example here where we changed the name of
the video game object. If I'm passing data by value, then why is this change
persisting outside of the method? Surely this doesn't make sense. Well, this is because
we're passing a reference type by value. Like I said, when you
pass parameters to methods by default
it's by value. However, we're passing
a reference type. Remember before we talked
about reference types, which are complicated objects. They can be arrays, lists, all things like that. And this is stored
in the heap area of the memory, but like I said, there's a pointer which is
stored in the stack area of memory which points to
this data in the heap. When this method is called, yes, it is copied to the method, but the heap memory
is not copied. Only the pointer on
the stack is copied. Now this seems counter
intuitive really because, yes, we're passing this
reference object by value. However, because it's
a reference object, we're only merely copying the
pointer inside this method. Here we're working with a copy of the pointer which is
stored in stack memory. However, it still points to the same area of
memory on the heap. In this main method, we're pointing to the area
of memory on the heap, but also inside this method. Even though we're working with a copy of the pointer
on the stack, it's still pointing to that
area of memory on the heap. This is why the title still changes because even though we're working with a
copy of the pointer, it still points to that
same area of memory. This is why the title still
changes inside the method. And we can see here, once
the method has been called, the changes still persisted
after the method's execution. In here, I appreciate this
is quite a lot to take in, but if you look at
the previous tutorial and also this one a
couple more times, you will understand it
and you will get it, I promise when I said a copy of the pointer is passed
into this method here, for example, if I now work
with this copy of the pointer. So this game here, I can initialize a new
object, a new instance. What that does, it allocates
a new area of memory. Here, I'm working with the copy of the
pointer right here, but I'm saying, okay, now create a new object on
this copy of the pointer. So what this is going to do, this is going to work with entirely new copy of the data
and put this on the heap. What we're doing here, once
the method has been called, we're outputting the
game's title here. In fact, let's put this here. Now we have a new
instance of game. We're setting the title of
this new instance to changed, and then we're outputting it. And we're still outputting the title after the method here. What do you think
will happen now? Well, let's take a look.
Let's run the program. You can see now something slightly different has happened. We have our original
title at the start here. Then inside the method,
it's been changed. However, after the
method now it still retained its original
title from before. Why is this what
is going on here? Like I mentioned, this
is a reference type. By default, it gets passed
by value inside the method. We have a copy of this
reference types pointer, which is in stack memory. We're now giving it a
new memory location and setting that new
location to change. However, outside of the method, this has no knowledge of
this new memory location. This is only inside the method
that this is happening. Only inside this method
has the knowledge of this new area of memory on the heap and
that we're pointing to it. However, this change is
not persisted outside of the method rather than working with an existing
copy of the pointer, which again, will
affect the heap. Just like out of here, we're actually allocating
a new memory area on the heap and pointing our
copy of the pointer to that, and that is why this happens. Let's take a look at
one more example here. Again, this is going
to have pretty much the same output as our
previous reference type, which was an instance
of a video game object. But here we have another
reference type, a list. Again, it could be
any reference type, It could be an array, it could be a dictionary, it could be many
different things. This, again, is stored
in heap memory. A list with four integers, we're outputting the
count of the list, and then we're passing
the list to this method. Now, by default it's
passed as value, but this is a reference type. A copy of the pointer is
copied to the method. Now the method can work with
a copy of the pointer which points conveniently
to the same area on heap memory as this
one. Outside the method. We're then adding two
numbers to the list, then outputting the list count. Once the method is ended, we're outputting the
list count again. What do you think
the results will be? Well, let's take a look. You can see the counts of 466. That's because the method
is adding two numbers. And once we're out here, it is pointing to the
same area of heap memory, it's going to retain that count. Now in the method, if I just modify the
list slightly here. Now inside the method, this list is being
passed again as value. But it's a copy of the pointer. With the copy of
the pointer and now pointing it to a brand
new area of heap memory, and then adding two numbers
to this brand new list. What do you think
the output will be? Now let's run the program. You can see we
have four to four. You can see our initial list
has four. That's correct. Inside the method, we're
creating a brand new list. It only has two numbers inside. That's where the two comes from. Now the method is finished, we still have access
to this original area. In heap memory, it's
outputting the four. So you can see it works with all different types
of reference types. And this is default behavior
of methods in C Sharp. So I'm going to come
full circle now. At the start of the
previous tutorial, I said, why do I need to know about
stack and heap memory? Why is it important? Well, you can see if you
don't have any knowledge of stack and heap memory
and value type variables and reference type variables, then unexpected
things can happen. Unexpected things are
quite a big problem in software for obvious reasons. This is why it's important, and here's an example
of this in practice.
64. 14-3. Method Parameters - Passing by Reference (The ref Keyword): The ref, key word passing
method parameters by reference. If you haven't watched my
previous two tutorials on this subject where we talked about stack
and heap memory but also passing by value, then I highly recommend you watch these before
proceeding with this tutorial as they tie into the concepts outlined
in this tutorial. In the previous tutorial, we talked about how various
different object types when being passed as
parameters into methods. By default, they're
passed by value, that meaning a copy of
the actual value or a copy of the pointer is created and the method
works with the copy. Now I'm going to talk about
passing by reference. Now, passing by reference is
not default behavior and it includes talking about
a brand new keyword called the ref keyword. So how does this work? Just as a little refresher here, we're setting up two integers,
outputting their values. Then inside this method, we're passing them
in as parameters, resetting the values to zero, outputting the variables again. Then when the method is done, we're outputting the value
of the original variables. And you can see we're
passing these by value. The method only works
with a copy of them. Therefore, the data is never changed once the method
has finished completing. Now what I'm going to do
is change this slightly. I'm going to pass
these value types. Remember value type is integer, boolean, simple types
stored on the stack. Now I'm going to pass
these by reference. To pass something by reference, you just prefix the
variables here with the ref keyword in the
method parameters. Here we do the same thing, we just add the ref keyword. Now what do you think
the output will be? Well, let's take a look. So you can see it's exhibiting the behavior of
the reference type from the previous tutorial. Remember when we
modified the value of a reference type and it remembered it after the
method had been called? Well, this is what's
called passing a value type by reference. And we can do this by
adding the F keyword here. What is the advantage of this? Well, passing a value
type inside a method, it doesn't create a copy
of the value anymore, so no copy is being created. It's pretty much saying,
okay, hey method. I'm going to pass you
these two variables here, they're value types,
but I want you to pass you the reference
to them in memory. I want you to work with these. And anything you do to them, the changes will be reflected. So this is passing
a reference to the area in stack memory
for these value types, and now they're being
passed as reference. We can work with these
directly inside the method, and any changes we
make to these will be persisted once the method
is finished executing. So you can see here
I've just changed them, now the change has
been persisted. So you can see now we understand the default behavior in the last tutorial which
is passing by value. It's easier to understand the other terminology which
is being passed by reference, and that is using
the Ref keyword. Okay, we've looked at passing value types like
integers by value. We've looked at passing reference types like
complicated objects by value. We've now looked at passing
value types by reference. And now to complete
the quadrilogy, we're going to look at passing reference types by reference. Here's the example.
Here we have our list of integers that we
looked at before. We just have four
numbers in there. And then inside this method, we're adding two
numbers to the list. And then outside, we're just outputting the count of
the list along the way. We looked at this before and you can see here's
the output here, because by default we're
passing a copy of the pointer, but it points to the same
area in heap memory. So you can see the changes being persisted once this method
has finished executing. But remember when we
talked about the fact we can actually set
up a new location in heap memory and take a copy of our pointer and give
it a whole new location, and that changes the result. You can see here the change is not persisted in this case. Now I'm going to qualify
this with the ref keyword. I add that here when
we call the method. And I add that here in
the parameters here. What do you think is
going to happen now? Well, let's take a look. I'm going to run
the application. You can see now the
change has actually been persisted once the method
has finished executing. Why is this what's
going on here? Well, you may have
already guessed it. When we pass something by reference using the
reference keyword, just like we talked
about before, no longer creating a copy, we're not even creating a
copy of the pointer anymore. We're pretty much
passing the pointer in stack memory to this
data in heap memory. We're passing the pointer
itself to the method. The method is now
working directly with the original pointer
to this information. Now we're setting up a brand
new object here, a new list. But we're not working with
a copy of the pointer, it's the original pointer. We're pretty much just creating a brand new list over the top of the original one and then
adding two numbers to it. If we run the application now, just like we saw previously, you can see here it's
being persisted. That's the difference here. When using the ref keyword, we're no longer
copying anything. We're not copying
the value types, but we're also not copying the pointers when
using reference types. Why is this useful? Well, then our methods can
work with our original data, whether they're value
types or reference types, and the changes can be persisted once the method
has finished executing. That's the power of the
ref keyword in shop. This completes this three
tutorial series on stack, heap memory, and reference
and value types in C shop.
65. 15. The struct Keyword: In this tutorial,
I'm going to be talking about structures in C. Sharp structures use
the keyword struct, but what are they and
how do they work? Well, structures are
very similar to classes, and this tutorial
assumes you know a little about how classes work, how inheritance work,
perhaps interfaces and also value and reference type variables and also the
read only keyword. I've done tutorials on
all of those previously. If you've watched
everything so far, you'll have a full
understanding of this tutorial and you're going
to hit the ground running. What is a structure? Let's
take a look at this example. Right here I have
a square class, let's take a look at that now. It has two private fields here, the width and the
height of the square. It has a constructor which
sets up those fields. It has a sample
method here that just calculates the area
based on those. And also two public properties here that expose the
width and the height. So it's quite simple.
So what I'm doing here, I'm instantiating a new object, and I'm outputting some
sample things to the window. If I run the application now, a square with height four and width five has an area of 20. So it doesn't really
do all that much. So let me introduce a
structure now and what it is. So this go over to the
square class here. And I'm just going to modify this class keyword and I'm going to put
structure like that. So if you watch my
tutorial on interfaces and enumerations where we create a brand new class and just
modify the class keyword. It's quite similar
in that regard. And now we have a structure. This square is now a structure. It's no longer a class. But you can see there's
no errors here. There's no red squiggly lines. How is it I've just modified this whole entire class
and there's no errors. Does the application even run? Well, it looks like it runs. And we have exactly
the same answer, what is going on here? Now this is where structures and classes confuse
new developers or developers that
don't really have an understanding of value
types and reference types. Structures and classes can seem very similar
in how they behave. You can see here, I've
made a structure, It has private fields, it has a constructor, it
has methods, properties. What is the difference here between a structure and a class? Can I just use structures
now instead of classes or shall I ignore structures completely
and only use classes? Well, the answer is
you can use both. One of the main differences
between structures and classes is that structures
are value types. Now, how does that work? Well, we talked previously that classes are
reference types. If I put this back here, square is now a class. I just uncomment
this method here. Now this method here, I'm
passing in the square, which is now a class,
into this method. And I'm modifying
some properties here. I talked about this previously. When you pass a reference
type like this one here, this is a reference type, it lives in the heap area
of memory to a method, then it's passed by reference. That means the method can
access the memory on the heap. It works with the
original object when the method is finished. Here we still have
access to the changes made from with inside this method if I run
this application, now we're going to
see these changes reflected in the output here. Let's take a look at
that. You can see here 2,020.400 for the area. It's a reference type
variable right here. It lives on the heap.
Now let's change this back into a structure
and see what happens. Now this is a structure
I mentioned previously. The structures are value types
and not reference types. These changes will not be
reflected in the output. That's because the
method works with a copy of the value type. Anything changed in here, it's just reflected on the copy. The changes will not persist. We're going to see 5.4
like we did previously. As you can see there,
that is one of the main differences
between classes and structures is
that classes are reference types and
structures are value types. That's one main
feature of structures. Let's take a look at
some other differences between structures and classes, as they are quite similar and they seem to operate the same. Let's talk about
the differences. I think that will let you better understand about what
structures can do, the advantages and also
the disadvantages. With structures, we cannot
use inheritance classes, for example, we can
inherit from a base class. But when we try to do
that with structures, and we hover over this, it's shape in interface
list is not an interface. What does that mean?
Quite cryptic, isn't it? That's because with
structures you can actually
implement interfaces. You can work with
interfaces, It's no problem. This error here, it's expecting an interface
because that's pretty much the only thing in that regard that you can
do with a structure. But when I try to
inherit from a class, a base class, it doesn't let me do that because
it's not possible. The whole concept of inheritance does not
exist with structures. That's one advantage a class
would have over a structure. We cannot inherit
from a base class, but the structure
itself also cannot be an abstract class
or a base class. And that means we can't have virtual methods, for example. You can see here when
I tried to do that, it's not even valid, it's because it's
inside a structure. So we can't use the
keyword virtual, which means we can't override, which means we cannot do
any polymorphic behavior. And remember, that's the
concept of method overriding. For example, we
can't use virtual, we can't use abstract. So we can't pretty
much use anything with regards to inheritance
or anything like that. With structures, there are a lot more simpler
types than classes, so think of it that way. A structure is more
simple than a class. Let's talk about maybe an
advantage of a structure here, or maybe why we
would even use one. Why even bother? Why don't we just use classes for everything? Well, structures don't have a heavy memory footprint like a reference
type object would. For example, I have
a video game object right here, video game class. Inside here it has
private fields linking to other reference
types like a game class, a list of integers, some strings, an enumeration. This is quite a heavy footprint and this lives on the heap. For that reason, we don't
put it on the stack. But if you use, for example, a structure for a
very simple class, for example this square
class right here, It only has simple value
types like just some doubles. Even if it had Booleans and
integers, things like that, it's going to operate
a lot quicker than allocations and
allocations on the heap. So when working in the
stack area of memory with simple value types
and even structures, then it's going to
operate a lot quicker. And allocations, again, are a lot speedier and
cheaper as well. So this is an advantage
of using a structure. So you may think, okay, what if I have a reference
type inside a value type? For example, a list of integers is a reference
type variable. And then I go ahead and put
this inside my structure, which is a value type. Yes, it's possible. You
can see there's no errors. The application is going to run, but this is considered
bad practice. You should not do this. This kind of defeats
the point of using a structure
in the first place, which brings me back
to my next point. Only use a structure if you have a container for
simple value types. For example, this square here. It has a width
which is a double. It has a height
which is a double. If it has a color, maybe you could represent
this by an integer. And that integer might reference something
to do with a color. For example, white
might be zero, Black might be one,
Red might be two. These are working with
simple value types. Here, a structure in
this instance would be perfect because it
itself is a value type. But I'm also using
value types within. I never plan on
using inheritance, I never plan on
using polymorphism. I never plan on other structures or things inheriting from this. Therefore, a structure would
be a good choice for this. It's simple, it's quick, it uses value types. I never want to expand on
it to do with inheritance. If all those boxes are
checked, use a structure. But as soon as we start
thinking things like, okay, I think this square should inherit from a base class shape. And maybe the color
could be an enumeration, maybe it would have a list of pixels and things like that. And we start
introducing inheritance and heavy and reference
type fields here, then no, we don't
want a structure, we want to use a class. So basically in a nutshell, use a struct if you
have a cheap object, but use a class if
you want to expand it and use heavy
reference type objects. That's basically
the difference and why you should use one
and not the other. So one of the main advantages at has over being
a value type and everything to do with
that is that you can mark the entire
structure as read only. Now if you watch my
tutorials on Read Only, you'll understand what it does. It's an immutable data type. Once you've set a value,
you cannot change it. And there's lots of
reasons for that. If I try to mark this
entire class as read only I haror over this you can say
it's not valid for this item. But if I make a read only structure like this for example, then there's no problem at all. Obviously, there are a couple
issues to do with that. So you can see
instance fields of read only structure
must be read only. These do need to be
read only as well. The other thing, of course, we can't use the set modifier
if things are read only. We have to either initialize in the field declaration here, so we initialize here or
within the constructor here. If you watch my
Tuchoil on read only, you will remember that
and understand that, but I thought I'd just
mention it again. With structures, you can mark the entire structure
as read only. Which you cannot really do on
a class using this keyword. And you'll see maybe moving forward with your
programming ventures, you'll see this is
quite common practice as well when working
with structures. This is one powerful
thing you can also do when working
with structures. But I think the main
takeaway from this is don't be afraid to use
structures and experiment, but only use them for
simple containers. So things like squares where
you have simple value types. As soon as you start talking about heavy loaded
reference types, then in that case, use a class. But structures are very
good for working with like quick muck up applications
or simple things like these. I hope this tutorial helped you.
66. 16-1. The object Data Type - Boxing and Unboxing: In this tutorial,
we're going to talk about the object data type. And it looks
something like this. You may have encountered
the object data type when writing to the console. For example, when we
write to the console, there's lots of different method overloads
we can use here. But you can see one
of the parameters here is object for example. What is that? How does it work? Well, let's take a look at
what the object data type is. If you watched my tutorials on inheritance and also value
types and reference types, then understanding
the object data type will be quite easy for you. Now, the object type is the ultimate base class
for all data types, all types user defined, Whether we create
instances of objects, reference types like arrays
and things like that, and also simple value
types like integers, bolenes, characters,
and things like that. It's the ultimate base class
for all of these types. It's a reference
type which means it's stored in the
heap area of memory. Also, it's like an
older technology. Now something came
along called generics. And generally, generics
is a better practice, although you do still encounter the object data type these days. And using the object
data type can present some issues and problems which
we will also talk about. This is the process of
boxing and unboxing. Let's take a look
at an example now, when I just said that
the object data type is the ultimate base type,
what does that mean? Remember before when I
talked about interfaces and we can pass the interface
around into methods, then when we implement
the interface, then we can pass
our objects around. If we have multiple classes
extending the same interface, we can just pass those
objects around freely. This is pretty much similar to how the object
based class works. Don't worry if you didn't watch those tutorials on abstract
classes and interfaces. I'm going to explain
it right now. Here, we're just
calling a method and we're passing a string. It just says hello world. The parameter is a string. Which is great
because we're passing a string and then we're
outputting it to the window. A very simple application. Now imagine this. I'm going to change this string to the object keyword,
just like that. Now let's run the application. Again, you can see we have
exactly the same result. Why is this happening? Well, it's simply
because a string like this one here satisfies, that is a relationship. And it is an object just
like an instance of a class. For example, a video game class, a dog class, an animal class. There are also classes, but they are also objects. This object keyword here can represent pretty much any
data type in the system. Bouls, strings,
and even integers. For example, 3456. The output will be the same, and there's no problems
with compiling the project. Here we have an integer here, 3456, we talked about it before. Simple integers,
strings, characters, boolenes, they're
all value types. They live on the stack, in the stack area of memory. However, objects,
they're reference types, these are stored on the heap. What happens here, there's an implicit conversion
happening here. This integer that
we're passing in is being converted into
an object type. This process is called boxing. If we then convert this object value
back into an integer, then this is called unboxing. If you don't believe me,
I'll prove it to you. Now if you work with an
object type like value here, it offers a few methods
that we can use, one of them being
called get type. What that will do, it will get the underlying type of
this object value here. Right now we're passing
an integer in here. If I run the program, you can see it's outputting the underlying type
of the object, which is an int 32, a 32 bit integer. Similarly, if I
pass in a string, say hello, then we're going
to get a string for example. You can see this is
the underlying type of the object right here, and we can get that using
the get type method here. Let's talk about boxing
and unboxing right now. Let's first talk about
boxing. What is boxing? We have an integer
here called numb, and we're initializing
it to 1234. Now what we're doing is putting
this integer into a box, hence the name boxing. We're basically saying, okay, I want to create a
brand new object. Remember this is the ultimate
base class for all types. I want to give this
the value of num. Now OBJ should equal 1234. Now I want to change the value
of this num here to 100. Do you think this value
will change with it? What I'm doing, I'm outputting two of the values right here. If we run the application, the value of num is 100, which is true because
we changed it. But you can see this is not reflected to our object
value right here. What is going on here? I thought object was
a reference type. When something is
a reference type, we have a reference to
that area of memory. Well, this is the
penalty of boxing. What happens here when
you box something, you're pretty much putting this integer inside
an object box. But because object
is a reference type, all objects are stored in
the heap area of memory. Simple value types like integers
are stored on the stack. What happens here
when we're creating a new object and we're
setting it to numb, here, we're pretty much copying
this whole entire object, allocating some extra memory
on the heap area of memory, putting that value in there. And then also creating the pointer on the
stack to point to it. A lot of things are happening
when you do this here. Now this is implicit, which means it happens
automatically behind the scenes. You don't have
control over this. Boxing, a very
expensive operation when we looked at
our example before where we passed an integer into the method and we had
a parameter of object. All of this happens
behind the scenes. A whole area of memory on the heap is allocated
just because we're passing an integer and it gets implicitly converted
to an object type. This is the penalty of boxing. It's also something we should
consider very strongly, especially when creating
large scale applications. Is there a better
way of doing this? Maybe you should consider of overloading the method instead. Like when we have
console right line, we have all these different
method headers here. We can take in a char array, a decimal, a double afloat. But once we have all these
possible values yes, then there is an option
to take in an object. But it's not mandatory. There are design things to consider when using objects
here, like this way, when you box certain data types, we could box a string, we could box a character, but in principle, this
process is called boxing. Now, the opposite of that, as you may have
guessed, is unboxing. What is unboxing? Well, unboxing is pretty
much the opposite. And that's converting
a reference type, like object stored on the heap, remember the heap area of
memory back into a value type, then stored in the stack. This is the opposite of
boxing, and that's unboxing. It's doing the
process in reverse. Let's take a look at an
example of unboxing now. Now I'm going to unbox
this object here. Remember, the process
of unboxing is converting a reference
type into a value type. Let's take a look
at that. Now, I want to convert it
back into an integer. If I convert it to
a different type, then there's going
to be an error. We're going to have a
type conversion issue. I want an integer out of
this whole operation. That's the point I'm on boxing the object back into
its original type. I set up an integer
called result. Now what I want to do is convert the object to the
expected data type. This is the expected
type I want, this is the conversion. I want to convert this
object to an integer. And this is the process of unboxing objects
stored on the heap. I want to convert it
to a simple data type, and now it's going to live
on the stack right here. This result integer here. Now if I output the result
to the console window, let's have a look at the result. You can see how I have my
original value here, 1234. Now perhaps you notice one thing about this tutorial,
and that is, hey, I'm introducing this
object keyword here, this object data type, but you shouldn't really
use it that much. Yes, I appreciate that's the general theme
of this tutorial, but it's good to
be aware of this. In the early days of C Sharp, it was quite common to convert various data types this way. So we convert it to
a reference type and back into a value type. And that allows us to pass different data types as the ultimate kind of
base class object. So it was quite useful, but then things
like generics and other things were introduced
which kind of pushed this whole object
notation of boxing and boxing out of practice
and out of fashion. But it is something
to be aware of, namely because perhaps
you might be working with older systems or you might be working with systems
that tie in with yours. Like it's called
interoperability, where your software links
with another piece of software and you will encounter
this object data type. As you can see, it's
still in use today. Console right line
takes an object as a parameter and
many other methods and classes also use it. But it's good to know
the principle of the object data type and the expensive process
of boxing and unboxing, which is implicitly
converting data types, value types to reference types and then back again
to value types. So there's quite a
big overhead with boxing and unboxing in C sharp.
67. 16-2. The dynamic keyword and Dynamic Type Checking: In this tutorial,
we're going to be looking at the dynamic keyword. And the dynamic keyword
looks something like this. But before we talk about
the dynamic keyword, let's just step
back a few steps. If you watch my
previous tutorials where I talked about C Sharp, the fact it's a strongly typed and also a statically
typed language. So let me just talk
about that for a second. A statically typed language
is where the variable types, for example, an
integer for example, is known at compile time. That's when I click this little green play button right here. The software compiles. And if there's any problems, the compiler will alert me, the software won't compile. And this is a statically
typed language like C sharp. This process is called
static type checking. Static type checking, however, what if I told you
that there was also something called
dynamic type checking? What is dynamic type checking? This is where the
variable types, for example, are
known at run time. If there's a problem with the types or anything like that, we can compile the
software just fine. However, if there's an error, we won't know until the
software is actually running. What do I mean by all of this? Well, let's take a look
at an example here. Here I have a sample integer. I'm initializing it
to the value of 55. Then I'm just outputting
it to the screen. It's not really doing much. However, what if I
want to maybe now assign a string value
into this integer? If I just type hello, for example, you can see
there's an obvious error here. It cannot implicitly convert
the string to an int. That's because the type of
this variable is an integer. But what we're trying to do here is stuff a string into it. It's not going to letters. Not only that, but our
program will not compile. You can see there's
an error here. This is an example of the
static type checking. It knows it's an integer, so it's an integer type. But now we're trying to
put a string in there. But we're actually alerted to this problem right
now in development. So this is known as
static type checking. However, with something
like dynamic type checking, then you won't be
alerted to this error. Everything will look fine, the software will
compile just fine. But unless you do something about this particular
error here, you will be alerted about
this error during run time. So, there are other programming
languages out there, for example Python or Ruby. Now, these are dynamically
typed languages. That means, for example, we can do this and the software will compile just
fine, it's no problem. However, you will be
alerted about this error during run time while
the software is running. This is called runtime and
this is where the error may present itself
at compile time. This is where C Sharp can catch these potential errors
to do with types, and that's called
statically type checking. However, at run time in
languages like Python, Ruby, then you'll be alerted
about these type errors. For example, during run time, and that is called
dynamic type checking. Now I've talked about
static type checking and dynamic type checking
and the differences. It's going to be easier to explain the dynamic keyword now. So under the hood,
the dynamic keyword behaves pretty much like
the object data type. If you watched my previous
tutorials where I talked about the object data type and it's canal considered to be the base class for
all of the types, for example the base class
of double integer bolen. But not only that,
but things like lists and custom objects
and things like that. So if you remember
and understand that detail about the
object data type, then you're going to
hit the ground running with regards to the
dynamic keyword. Now let's take a
look at an example. So what I'm going
to do now is do an example with the
object data type. So this variable
here called test, is going to be a type object. What I'm doing is
storing a value here, 35.5 which could be a double. For example, it looks
like a double to me, but there's no
problem here because object is like a
base class here, it's going to accept
that value just fine. But now we're trying to
increment this value of test, which is data type object by 7.5 It looks like we're
adding a to a double. Which should be fine when
we had it as double before. It worked with no problems. So you can see here,
there's no problem. But now I've turned this into an object data type,
there is a problem. So if I highlight this, it says operator plus
cannot be applied to object and double when
working with object, we talked about
boxing and unboxing. What I'm doing here, I have
a simple data type here, 35.5 which is like a double, and I'm stuffing this
into an object data type. Now if you remember from before, this is a reference type, so it's stored in the
heat area of memory. What we're doing is boxing
the value here into test. When we try and increment the value, there's
a problem here. We can't add 7.5 to
this value here. What we have to do here when incrementing the
value, for example, is explicitly convert
this object data type to a type we can work with. What we're trying to do is
add 7.5 which is a double, so I have to convert
this to a double. We can convert it
to a double using the convert static
class that we've been using all along in
the previous tutorials. And that's going
to work just fine. What I'm doing here is
unboxing the value here. I'm boxing here, I'm unboxing. There's a bit of a
performance payload here when we do the boxing and unboxing like we
talked about before. But it works just fine converting
the object to a double. Then I'm adding a double to it, then I'm storing the value
back into the object, so I'm re boxing it again and then I'm
outputting the value. If I run the program, now you see I have the value 43, which looks about right. You can see it
works. No problem. I can actually add
values together. I can even add five here, for example, and it's
going to work just fine. This is a bit of an
advantage of using something like this over
individual data types, But there is a performance cost. But the point I'm trying
to make is when you use the object data type and you
wish to modify the values, you need to do this
unboxing here. You have to do an
explicit conversion here. Now, with the dynamic keyword
I'm about to introduce, I said it's very closely tied
to the object data type. It behaves very similarly. But we don't need to do this explicit
conversion right here. And that's not the
only difference. One of the main difference
is that it provides dynamic type checking in
a C Sharp environment. So let's get started with
the dynamic keyword. So the very first
thing I'm going to do, so you understand
it a little better, is to convert this example
using the dynamic keyword. So what I do here, I define this variable
as dynamic here. And because it's not
the object data type, and we don't need to
explicitly cast anything, we don't need that
cast right there. So if I run the program now you can see it's working
just like before. It's not complaining about adding a value to an
object data type. So you can see there's a considerable
advantage right here. We don't need to explicitly cast our variables, for example. So that's pretty good. And
like I mentioned before, it works like the
object under the hood. So it's almost like, you know, the master base class
that works with integers, bouleenes and all
things like that. So that's the first
advantage of using dynamic. We don't need to
explicitly cast anything, so we don't need
to explicitly say, okay, make this an integer. So therefore we can now add an integer to it or
make this a double. So we can add a double to it. We don't need to do any of that. It looks perfectly fine. Looks, so we've defined
it as a double, now we're adding
an integer to it. All of the conversion
casting boxing and done boxing is done
behind the scenes. We don't have any
visibility of that. It's all done for us. So that's one advantage of this, that complexity is
taken away from us. Watch what Als can also do. For example, we initialize, this is like a double, and then we want to
add an integer to it. Now, what if I say test
equals hello, for example? What do you think will happen? Now let's run the application, what it looks like,
we're outputting hello. So what I'm going
to do, I'm going to add some breakpoints here. We're going to enter break mode when we run the application. And then we're going to analyze this variable test down here. So let's bring this up so
we can have a better look. Right now, you can see we have a dynamic object right
here, which is test. And it doesn't have a
value yet because we haven't executed
this line of code. Once I step over that, we can see that test is now, because we've put a
double value into it, now we're incrementing
the value by five, which seems pretty fine. So you can see it's
still a double. Now, trying to put a
string value into here, if we step over this, you can see now we have
a dynamic string here. So you can see it's quite
flexible in the way it works. It pretty much just throws out
the whole concept of types or at least hides the concept
of variable types from you. So while developing
applications, it may feel like
all that complexity is taken away from you. You don't need to worry about is it a string, is it an integer. Perhaps Python programmers, or if you've done
some Java script, you might find this
really useful. But however, errors can
occur during run time, and this is when your
application is actually running. So there are a few
problems associated with the dynamic keyword that you
have to be careful with. So the dynamic keyword, it probably sounds
quite great to you. We don't have to
worry about types, we don't have to convert
to different types. We can just use it
for everything. You know, why not? And maybe there's a slight
performance here, but otherwise it seems
pretty good, right? Well, let's talk about the downside of using
dynamic right now. But first I'm going to introduce an example where we work
with some custom objects. So what I have here, I have a video game class,
it's quite simple. It has four private fields, a constructor, a sample method, and just a sample public
property right here that just gets the video game
title. It doesn't do much. I've instantiated the class. Here I have a video game
object called Game One. If you've followed my 00
tutorials from before, when we make use
of this instance. Here we can see various things. We can see our get
publisher method. And we can see our property
right here, the title. We can see this when this
window pops up here, this is like Visual
Studio helping us. And another word of that
is called Intellisense. And what Intel sense does, it just gives us some nice
autocomplete features. It saves us from typing. For example, we can double
click to this and then we have access to the
method number one. We know the method is there. Number two, we know we
can access the method, it's not private or
anything like that. Number three, if we
double click it, we don't have to
worry about typos spell checking, so
it's quite good. It also gives us
parameter types we can use and also lets us
know about return types. So Intel sense, otherwise
known as visual studio, helping us is a
very good feature and I highly recommend using it. However, when using
the dynamic keyword, Intellisense is not available. Now, there is a good
reason for this, but it is one of the
big disadvantages over using the dynamic keyword. Let's take a look at that now. Right now, I'm just
setting up a game here. Then I want to get
the publisher, for example, let's just
store that in a string. I'll store it in a
string called Pub. And then I just want to
output it to the window. Not much is going on here. It should output
Blizzard, for example. Let's run the software now, and we can see Blizzard. It looks like it's
working just fine. Now let's turn this
into a dynamic type. Now I have a dynamic
object called Game One. It has the value of the new instance of
the video game class. Like I said, it doesn't have
to be a double an integer. It could be a complex type,
it could be an array, a list, or even a custom class, like the video game class. Absolutely, no problem
doing that at all. Fully supported by
the dynamic keyword, And again, this is like the
object behind the scenes. Everything is fine so far. And if I run the application, we get exactly the same
result, no problem at all. But watch what happens. Now I put a dot after game one. You can see we've lost all
of that in tally sense. Visual Studio is now
refusing to help us. We don't know what
methods we have available unless we actually, you know, kind of look at this and maybe copy and
paste them in. However, it has a lot
of problems this way. The thing is, it relies on
Earth not to make mistakes. Number one, like I said before, maybe this is a private method, so we can't even access
it outside of this class. So therefore, you know, we could create a whole
big problem here. So if I run the application, now it's saying it's inaccessible due to
its protection level. Well, what if I made a typo? What if I put F here? You can see it's not
highlighting it red. Run the application and it
doesn't contain a definition. Well, that's because I spelt it wrong and it's an accident. But I don't have visual
studio helping me. I have zero Intellisense. So this is one of the downsides of using the dynamic keyword. You have absolutely no
intellisense at all. And intellisense
is really useful, and a lot of people
take it for granted. But it gives you
all the methods and properties that you can
actually use on an object. So you may be wondering what
was that sorcery before where you misspelt publisher
and there was no red line? Why was that? What's
going on here? Why was the program
able to run you? That's normally not allowed. Well, yeah, that's
true because if I turn this back into
a video game object, you can see we get the red line. And that's because at
the start of this video, I said that C Sharp was a
statically typed language. And that just means everything
is caught at compile time. So I can't even compile the application because this is where the errors are caught. However, when using
the dynamic keyword, then all of this is gone away. Nothing which is dynamic
is caught at compile time. So the error is gone away. The program can compile. The program compiles when the black window pops up,
as you can see there. But now the error is
actually caught at run time. And this is the error
that gets thrown. It's called a run time binder
exception, right here. So run time binder exception. So this happens at run time while your software
is actually running. So in a nutshell, when you use the dynamic
keyword like this, visual studio just
gives you free rein. It literally says, okay, do whatever you want. If something's dynamic,
call any message you want, call any property you want. You know, it doesn't matter. I'm going to give
you no red lines. I'm going to let you
compile your software, you can do whatever
you want to do. You can introduce human error, pretty much You have free reign. So that's an advantage, or perhaps a huge disadvantage, of using the dynamic keyword. So the choice is
yours in that regard. But programming languages
like Python, Ruby, even Java Script, these are
dynamically typed languages. However, C Sharp is a
statically typed language. So you may be wondering, well, why does a statically
typed language support this in the first place? You know, why do
we even have this? I thought this was a
statically typed language. Well, what if you want to create software that works
with Python software? For example, if Python and Ruby are dynamically typed languages, then maybe my software
needs to work with them. And a fancy way of saying this is called interoperability, or interrupt for short. If I want to create
software that works with someone
else's software, but they used a
different language, then this is where the dynamic
keyword is actually quite useful even working with
the document object model. Now this is something
HTML and XML use when using things like that. You just do not know
what methods and properties are available
until run time. This is why it's quite useful. Not everything is known
at compiler time. When your software compiles, sometimes it's only made
available to you at run time. So this is why the dynamic
keyword is really useful. So a couple of fancy bits
of terminology for you. If we have our simple
video game object like we talked about before
and we wish to say, call a method called
get publisher, then this is an example of
what's called early binding. And that just means, okay, this method is available to us, we're using it right here. Any errors will be
caught at compile time. When we click this
little gray button and the binding is done early, everything works,
There's no error. For example, if I did this, then there's an error
example of early binding. However, if this was dynamic and we try to
do this right now, we have no idea if this
method is available. We have no idea
if this method is public, private,
internal protected. We have no idea if I
spelled it correctly. However, when I run
the application, then the binding is
done during run time. Right now, okay? Yes, the method is available. We've just called it,
we've got a result. This is an example
of late binding, Early binding before late
binding during run time. A couple of things you
may hear in the future, but I thought I'd
bring them up now. One other thing I didn't
mention was dynamic. If you define a variable, for example a simple integer
or something like that, whatever you really want,
the type isn't important. You don't need to initialize it. You can if you want to. There's no harm in doing that, but it's not required. You don't need to say,
okay, this equals five. You can work this out later on. That's another thing you can
do with the dynamic keyword. One other thing you can
do with dynamic is even pass it into methods and
return it out of methods. I've just set up a sample
method called Echo. It's just going to echo the
value of the publisher. For example, I know for a fact game one publisher
which will get that for me, I have no Intellisense. I assume it's spelled correctly. Then we're just going to
output that to the screen. Let's comment that one out and then we'll call
the actual method. This looks pretty good. We're passing the
game object in which is dynamic as a parameter to the method and
echoing the result of the get publisher method.
Let's run the program. It looks like it's working. You can see here, but not
only like I mentioned, we can return the
dynamic keyword as well. So here I'm calling the method here that now takes
no parameters. I'm initializing a new
video game object, and I'm instantly returning it. But I'm returning
the dynamic keyword because I don't want
a video game object. And then I'm catching
the result here in a new dynamic game object, and then I'm getting
the publisher. So you can see equally it works as a return as well, dynamic. You can pass around
no problem at all. So let's summarize the
dynamic keyword right now. The dynamic keyword, we don't have to worry
about the types, we don't have to worry
about casting types. All the boxing and boxing
conversion is done for us. That's great. However,
there's a performance impact. Again, we have to
worry about spelling our methods correctly working out if they're
actually accessible. Lots of different things. In a nutshell, dynamic isn't used in a typical C
Sharp application. If you're just
making a calculator or something quite simple, you shouldn't really use
the dynamic keyword. However, if you're working with perhaps other pieces of software which have been developed
in dynamic languages, or maybe something
called a com object or the document object
model for HTML. This is where the
dynamic keyword shines and this is where
you should use it, because in instances
like that you don't have access to these methods
at compile time anyway. You may only have access
to them at run time. So this is where you would use the dynamic keyword
in this sense. So it's not used in
common shop applications. So it's one of those
with scenarios where you never
really ask yourself, should I use the
dynamic keyword. It's usually presented to you. Okay, yes, this definitely looks like I should use
the dynamic keyword. And that is what generally
happens when you're architecturing a new piece
of software, for example. So the dynamic keyword, it offers dynamic type checking, and it's basically
the object data type, but on steroids. Thank
you for watching. I hope it was useful.
68. 16-3. The var Keyword and Type Inference: Based on everything
we've learned so far. What if I told you that we
no longer need data types? For example, we don't need a
video game object data type. We don't need a list data type. We don't need a string
array data type, not even an Interble
or a character. And everything's fine and
the software will compile. What the hell is going on here? Well, let me introduce
something completely different. Now in this tutorial I'm going to be talking about
the Varki word in C sharp. It looks something like this. If you haven't watched
my previous tutorials on the dynamic keyword where I talked about dynamic
type checking and also static type checking, all that good stuff,
then I highly recommend you watch those before
proceeding with this tutorial. Otherwise, you're going
to have a harder time understanding the concepts
highlighted in this tutorial. So what is the Var
keyword? How does it work? Well, we can use the Var keyword when defining something
like a variable. For example, we have
an integer variable here and we set it to 55. We could equally
set this as a v, what looks like a Var data type. However, Va is not a data type. The keyword Var is
shorthand for okay. Figure out what data
type this actually is when you compile your
application, for example. So all checks using the Var keyword are
done at compile time. Now remember in our last
tutorial where we talked about the dynamic keyword and how everything to do with
a dynamic keyword was figured out at run time. For example, do
the methods exist? Do the properties exist? And then it kind of links it
together in a late binding. At run time, well, the Va is done at compile time. So for example,
if I try and call a method on a var variable, for example, then it's going to error if the
method doesn't exist. But we're going to
cover that later. Let's take a look
at a small example using the var keyword and
then we'll go from there. Let's take a look at a couple
simple examples right now. Here I have a local
variable here called test. But rather than giving it, say, an integer or a string
or something like that, I'm using the var keyword here. And as I mentioned before, it's up to Visual Studio and the compiler to work out
what data type this is. I say Visual Studio because I've just defined
the variable here. And if I hover over
it right here, you can see it thinks
it's an integer. If I change this to a string, it doesn't really matter what's in there. It can be empty. I hover over test, and now it's a string data type. What it does, it works out the data type based on
what you initialize it to. I've initialized it to a string. Here you can see when
I hover over it, it's a string data
type, just like before. It could be an integer
or even a double, for example, now it's a double. Now when I actually
compile the application, this is where it
works out if anything is valid or invalid based
on what you've done. This is the compile process
and this is where it actually figures
out what data type it is it compile time. That's a simple example there on how Var is not a data type. But you can see
it actually bases its data type on what
you initialize it to. What happens if I
don't initialize? Well, that's not possible. You can't actually
define something with the var keyword and
not give it a value because then the
system cannot work out a data type from
this whenever using the var keyword always
must initialize it from that it can work
out what data type it is, for example, a string. The process of working out the data type based on
the initialization value, well, there's a fancy
word for that and it's called type inference. You may hear that in the future. It's called type inference, and that's where we guess the data type based on
the initial value here. Now our local variable
here, the type, is a string because
this is based on the initialization
value here. What we cannot then do
is then just convert this to a totally different
type. You can see here. Cannot convert type into string
once this is initialized. For example, this
is now a string. It's pretty much a
string for its lifetime. We can't just then, okay, make it an integer,
make it a booling. We cannot do that
with the Var keyword. Let's take a look at an example with some more
complicated objects. Now for example, let's
define a game object. This is our video
game class where we just pass in
some sample values. Here, you can take a look at the class here. There's
not much going on. Private field, a constructor
and a sample method. What I'm going to do is just
call this sample method here called get publisher
back out here. I'm setting up a new
video game object, but I'm storing this
in a game right here, which uses the Var keyword. So now using this game object, you can see I have
full Intellisense here I have the full
visual studio help. Unlike the dynamic keyword, because remember in
the last tutorial when I talked about dynamic, everything is figured
out at run time. So we have no
Intellisense at all, because all of this is
figured out at compile time. Then I have full access
to the Intellisense. So I'm not going to make
typos, guessing methods, calling methods that are perhaps private and I'm calling them outside of
the current class. I'm not going to make
those mistakes like perhaps would using
the dynamic keyword. So if I run the application, now you can see I'm getting
the publisher no problem, and I have full access to
the Intellisense available. So let's talk about
a few pitfalls of using the Var keyword. What can't I do with it? And why is it bad? For example? Well, unlike the
dynamic keyword, Var doesn't really have
that much disadvantage or much negative impact. However, there are a
few disadvantages. For example, we cannot use
the var keyword with methods. So here I have a
test method here. If I try to return
something of var type, it's not going to let me. Similarly, if I use it as a parameter and just
give it a name, again, it's not going
to let me either. This is just simply because visual studio doesn't
have enough information available to guess the type based on a return
or a parameter. Or at least that's what
I'm led to believe. But you cannot use
the var keyword as a parameter to a method, or even return a
v from a method. It's just not possible. But with the dynamic
keyword for instance, you are able to, you cannot
with the var keyword. Let's take a look at one
more potential disadvantage of using the Var keyword. Now let's clean up some
of this stuff here. What I'm going to
do, say for example, I want to create some
financial software. I want it to calculate money, but I want a high degree
of decimal accuracy. I don't want to
lose money due to my software of not allowing
enough decimal places. It's quite easy to do. In an instance like this, I need a decimal data type. If you remember
my early tutorial where I talked about decimals, I talked about floats and
I talked about doubles. If you remember, decimal has the highest
degree of accuracy, so lots of decimal places. Doubles are somewhere
in the middle. And floats have the
least precision, the least number
of decimal places. I want a decimal because
I'm working with money, I don't want anything
to get lost. I'm going to create
a new variable. It's going to be using the var keyword and I'm
going to call it money. Now, I'm going to
initialize this. May it doesn't really matter
what value for example, but I'm going to put maybe
something like this. Actually, no, let's
just make it zero. So I've initialized it as zero and now if I
harver over this, you can see it's assumed
the data type is double. Now double is like a medium degree of accuracy,
but there's no error. You know, there's
nothing wrong with this syntactically.
It's perfect. The application runs. I'm outputting zero right here. Now the system doesn't know my intention, the
system doesn't know. I want to create an
application based on money. I actually want a high
degree of decimal places. I want this to be a
decimal behind the scenes. So how do I do that? Well,
when defining a decimal, you need to just
put m right there. And if I harver over money, you can see it's now a
decimal, not a double. But you can see that's
just human error. I could easily forget to write that m and now
I have a double. So maybe if I
compile my software, give it to my clients, they start using it for example. Then they notice that a little
bit of money is missing due to rounding because this
is assumed to be a double. So I'm losing a lot of degree of accuracy by making
that tiny mistake. This software is responsible
for losing money, and that is not good. And again, you might
not be losing money. You could be gaining money, but the fact is it's wrong. So I could easily forget to use this M here and get a decimal. So it is something you should be really careful with doing. So I'll just highlight this
to you now if I just set this money value to a high
degree of decimal accuracy, because we're
working with money, when I run the application, you can see all of this
accuracy has been truncated, so quite a lot of
information is missing. And that's just for the fact
of using an m right here. So, you know, it's
quite easy to do. Whereas if I were to find this as a decimal to begin with. And then I do
something like this, then you can see
there's a red line, so the software won't even
compile. There's an error. And it's pretty
much saying, okay, if you need a decimal you have
to use the M suffix here. I'm never making that mistake. If I explicitly define this variable money as
a decimal data type, That is one particular scenario where using a Var keyword
could create problems. In the future, I want to
show another example now to do with the Var keyword and a potential disadvantage
of using it. Here I have my video
game class right here. It has some various
fields in here. What I'm going to do,
I'm just going to copy these fields and move them into the main method right here so I can
illustrate something. What I have, I have these
various types here. I have integers, strings, list of integers, and also
a game object as well. What I'm going to do, rather than have these data types here, I'm going to replace them
all with the Var keyword. And you'll notice something when I change game info
to use the Var keyword, now we have to give it a value before we could
just leave it like this. What's called null,
It has no value, and we'll talk about null
in a later tutorial. But now it actually needs a value because it
needs to work out the data type from when you
instantiate the object. So now we can't leave
this empty like this. We need to give it a value. That is one important
thing to note. When using the var keyword, we have to initialize it. What I'm going to do,
I'm just going to change these into
the Var keyword. So we can see one
more thing as well. Now, the other disadvantage, maybe potential disadvantage, or at least awareness is that when looking at declared
variables here, it's hard to tell what
data type these are. Maybe we can figure
out console is a string and title is
a string, et cetera. But we can see the zero
and know it's an integer. But using this, especially anywhere else in
the application, we would have to hover over
the variable each time and work out that it's an integer by looking at this name alone. Obviously, there's
var next to it, so we don't see the
int datatype either. It's a little unclear at a first glance what
data type this is. Perhaps we can be
more careful with our variable names and
maybe call it rating int, or perhaps rating number. And then we know from
a first glance that, okay, it's a number. It's especially useful
when debugging, but it is just something to note when using the var keyword, especially declaring
the variables. Here, this kind of explicit information
with regards to the data type
has disappeared. We can really only have the
initial value to look at. We have to hover our mouse over each one just to get clarity
on what data type it is. So when you have large, complicated pieces of software, and you're trying
to debug, you know, hundreds of variables, it can be quite time
consuming to work out, you know, what type
the variable is, and maybe there's a type issue. Maybe you're trying to feed a string into an
integer, for example. If that's a potential bug, then it can take, you know, a little longer to work it out when we don't have
explicit types here. And we're kind of
having to hover our mouse over each one to
work out what the type is. And by no means it's
a deal breaker, it just forces you into a good habit of naming
your variables correctly. For example, a variable called rating number could be a
better name than just rating. It gives a bit more information about the data you're
storing in this variable. If anything, it teaches you
to be a better developer. The last thing I
want to talk about is when should I use
the Var keyword? Should I ignore it
completely and just retain it as a bit of knowledge or
shall I use it all the time? Are there any downfalls? Are there any practical reasons? Well, a lot of people actually use the Var keyword
for everything. I've looked at software and they don't even use data types, or at least hardly ever
everything has the Var keyword. I mean, there's nothing
really wrong with that, especially if you use
descriptive variable types. You're quite cautious
about when you define decimals and
floats, for example. So there's nothing really wrong with using
the Var keyword. You can use the Var keyword
for pretty much everything, or you can use standard
data types. It's up to you. But there are a couple
situations where the Var keyword does
have a few advantages. So let me show you those now. So let's clear out some
of this example here. Let's say for example, we're creating a
piece of software that manages a bunch
of video game stores. We have our video
game class here. Each store that
sells video games will have a list of video
games in their collection. It will look
something like this. However, we want to
manage multiple stores. Each store will have a
list of video games, but perhaps we want to catalog what every
single store has. In a situation like this, we would have a list of
a list of video games. And that will be like the Ultimate Game
Collection, for example. So in this case, look
at this data type here. It's quite long, it's
quite annoying to write, it's quite complicated
to look at even. You could even expand
that by saying, I have a list of
a list of a list. So you know the kind of
predicament goes on. You can see how big that is. But in a situation like this, you could use the var keyword. And that just
simplifies all of that. It saves a lot of typing. And you can see you have a nice handy shortcut there
in cases where you have quite large data
types here and you don't want to type it all
out and for whatever reason, in tell sense isn't
offering it up to you. Or maybe you want to
loop over it and you don't want to write out
this whole data type. It's quite easy just to
use the Var keyword. You know, it's no
problem at all. And, you know, in cases like
this you're not defining decimals or doubles and there's a risk of maybe losing
decimal precision, then something like
this is perfectly fine. It's quite an easy way to do it. And you can see how
quickly it was to type just three characters on the keyboard versus
all of this here. Just one example there, there's a couple more
examples as well, which we haven't yet covered, but we're going to
cover one of them. So one of the two examples is something called link queries. And another example is
creating anonymous objects, which we will be
talking about soon. And the var keyword is very good for creating anonymous objects. But to summarize, and
the takeaway from this tutorial is var
is not a data type. Var is just a nice
way of saying, okay, let's figure out the data type based on the initialization. And this process is
called type inference. So this is the var
keyword in C sharp.
69. 16-4. Anonymous Types: In this tutorial, I'm
going to be talking about anonymous types in C shop. If you haven't watched my
tutorial on the Var keyword, then I highly recommend
you watch that first before watching
this tutorial. So anonymous types,
what are they? Let's take a look
at an example here. Here I have a class
called video game, and I'm creating four objects. It doesn't really
matter what's in here, but there's a constructor, some fields, various properties
and things like that. So you can see in this example, I'm setting up four
objects here by prefixing them with our
classes like a data type. Then I'm instantiating
a new object with all these parameters. But in order to do this, I have to create a class. Now, my class has to
have a constructor. Well, it doesn't
have to have one, but I do have one
and I do want one. It has all these private fields, some methods, and properties
and things like that. So it has all of that
stuff in this class here, just in order to create
for objects right here. But with something
called anonymous types, we don't have to define a class. You see this class here
where we define video game. We don't need any
of this definition. We don't need this file. We don't need this class per se. So how does that work? Why would it benefit
us to not have a class but we need to
instantiate from the class? That doesn't make sense to me. Please explain anonymous types, they're useful for a
couple of reasons. One of the primary reasons
is something called Link. Now, we haven't
talked about Link, so I won't talk about that now. But another situation,
for example, say you're prototyping
a piece of software. You want to do a quick piece of software to make sure
something works. Or maybe you don't
want to create a whole class with lots
of methods and things. Because what you're creating is something quite
simple and quick. So there's a couple
reasons really. But one of the
benefits is speed, and another benefit
is if you're not creating something
particularly complicated, maybe it only has two properties and you're not
doing much with it. Then you can use what's
called anonymous types. So how do I create an instance of a class
that doesn't exist? Well, that's a very
good question. And it starts with
the var keyword. So what I'm going
to do, I'm going to simulate this video
game object here, but rather than using
the video game class, I'm going to use
an anonymous type. So there's delete
all of those and we're just going to use
this one as an example. How can I instantiate a class that doesn't exist
using anonymous types? Well, because the
class doesn't exist, therefore it's
anonymous, we can't really start it with
a class name here. This is where we
use the var keyword that we've talked about
in a previous tutorial. Now we want to give it a name, I'm just going to
call it game on. Now we need to instantiate
a new anonymous object. How do we do that? We
use the new keyword, but now we use curly braces. Now inside these curly braces, we're going to set up our
properties for our class. This line here pretty much
mimics this line here. The only difference is that we don't have to define a class. This class doesn't
have to exist. We can call these
whatever we would like. It doesn't matter because
it's an anonymous type. If I use my object here, if I put a dot right here, you can see I can access all of the properties that
I've defined here. I've spelled them using
crazy characters like Gampd, but you can see that
that appears in the list and I can actually
access this as a property. Right here we have a console
here, publisher and rating, you can see it doesn't
matter what I call them, it doesn't matter
what values I give. This is purely anonymous
because it has no name, it has no class. Because it's anonymous, we store it using the var
keyword into an object. Right here, you can see
this is quite powerful. We don't need a class, it's completely
anonymous, and to do that we just use
the new keyword here. But there are a couple
of exceptions with this. When we create an anonymous type like this one right here, we can only create
read only properties. There's no constructor,
there's no methods, there's no private fields. Imagine if this
class here called video game was an
anonymous object, then the only thing
you can have in here are read only properties, title, for example, publisher rating,
and their read only. You can only get the values, you can only set them once. And that is when you
define the anonymous type, right here, the
anonymous object, but behind the scenes, this is what would be generated when you create
an anonymous type. So read only properties, no constructors, no
fields, no methods. So they're the limitations of
using something like this. It doesn't really stop there. When creating anonymous types. Here what we can
actually do is put an anonymous type within
another anonymous type. We can create an array
of anonymous types. So lots of different things
we can do with them. Let me show you an
example right now. In this example, I have
an anonymous type right here inside another
anonymous type. If I use my animal type
here and go to dot, I can go to species
which is also an anonymous type and access the noise that
the animal might make. The species could be a dog, in which the name of the
animal would be a dog, and then the noise
would be a bar. For example, you can see I actually have cascading
anonymous types. They are quite powerful
in which they work. And you can see just like using the Var keyword like before, you have full control
over the Intel sense. You can clearly see everything
you specified in here. That's pretty cool. One thing
you shouldn't really do, but you can do is pass these
anonymous types to methods. Let's take a look at an example. Now, when I talked about
the var keyword before, you can't have var as a parameter for a
method, it doesn't work. What you would need is the dynamic keyword in
which this would work. If I then call the
test method here, I pass in our animal right here. And then we can access
it from within here. But because we're using dynamic, if you watch my
tutorial dynamic, we have no access to
the Intell sense here, but we can use it. However, again, we shouldn't really use dynamic
when we don't need to. It's really only recommended to use it when you
absolutely have to. I don't see much
situation where you may be passing an anonymous
type to a method. Really, they should just be used within the methods,
they're defined. But if you do need to do that, then yes you can make use of the dynamic keyword in order
to get around that problem. So you can see now
I'm using dynamic. I don't have access
to the Intel sense, but I now can pass this
into this method here. So let's check and
see if it works. So you can see here
outputting bark, It looks like it
works quite well. This is an example of
anonymous types in C shop because it's an anonymous
type and it has no type. Therefore, that's when you
would use the Var keyword. And you can see here you
can pass it two methods, but you would have to use the dynamic keyword
in order to pass it. But I do not
recommend doing that. Lastly, when creating
anonymous types, these are properties only, and once defined, they're
considered read only. And you cannot modify them, as you can see right here, those are anonymous
types in C shop.
70. 17-1. The null Keyword: In this tutorial,
we're going to be talking about the null keyword. The null keyword looks
something like this. What is the null keyword
and how is it used also? Why should we use it? If you watched my
previous tutorial when we talked about stack
and heap memory, and reference types
and value types, then you're going to understand this tutorial very quickly. Here are some reference
type objects here, like lists, strings, arrays, video game object for example. It's a custom class. All of these are
reference types, and they're stored in the heap, which is the heap
area of memory. To contrast that, these
are simple value types, so integers, boolings and
characters for example. Now, have you ever wondered
when you declare a variable, so we're not initializing it, we're not giving them values? You can see the
software compiles, it works, It's no problem. We've declared them,
everything looks pretty good. But have you ever
thought about what the default values
for these might be? If we don't actually
give them a value, what would the default
value be? Would it be zero? Would it be, what would it be? Well, let's take a look. I'm going to add a break
point at the end of here, and then I'm going to look
in the locals window. Let's run the application. Now if we come down here to
the locals tab right here, we can view various
things to do with our variables that
we've just defined. Here you can see our
reference types. We have our list here, we have our custom object here, our string array right here,
you'll notice something. The current value is no. But if you look at these
value types like the integer, the Boolean and the character, or their default values
are slightly different. Typically a value type will
have a default value of zero. If you represent Bolen as
zero, then it would be false. A boolen as a one would be true. You can see Bolen also has
a default value of zero. Even this character variable here has a default
value of zero. You can see a pattern here. It looks like
reference types have a default value of null or whatever null is value types have a default value of
what looks like zero. In this example here, what is going on here? Remember when we talked
about reference types? When we have a reference type, a pointer on the
stack is created. But the actual meat
of the operation, the data lives in the heap. The pointer on the stack points
to the data on the heap. Now we've declared a
reference type here. For example, this list and
its default value is null. Now what null is saying here
is it's a null reference. We have our pointer
on the call stack. This is in the stack
area of memory, but we don't yet have
anything on the heap, we haven't instantiated it. That means using
the new keyword. When we instantiate something
using the new keyword, we're creating something in
the heap area of memory. This part we're creating
the pointer on the stack. This part we're actually
creating the data on the heap and therefore
the pointer points to it. However, we're not instantiating
anything right now. We have our pointer
on the stack, but it's not pointing anywhere. There's no reference to
the data in heap memory. Therefore, the default
value is null, which stands for
a null reference. It doesn't go anywhere. However, as soon as we
use the new keyword, then the value will change from null and it will point
to the data on the heap. Think of null as
like nothingness or a null pointer or
a null reference. It doesn't really go anywhere, but maybe later on it will. For example, you can see here, this only applies to
reference type objects, complicated objects like
we talked about before. It doesn't apply to
value type objects. However, there is a bit
of a condition there. It does apply to value type objects if
they're marked as nullable. Now, we're going to talk
about nullable later. Don't worry about that. But for the purpose of this example, null applies when declaring reference type objects because we need a pointer, but
we don't have one. The initial value is
null, which is nothing. Let's take a look at a couple of examples now working
with the null keyword. So what I'm going to do, I'm
going to output a property, or maybe try and use one of these methods here of
these reference types. I'm just going to write
to the console window, I'm going to output a random
property of this list. For example, I'm going
to say list dot count. Let's take a look at
what's happening here. Now I have a red line. You can see use of unassigned
local variable list. It's not even letting me use this object because
it's unassigned. But wait, I thought it
was null by default. Well, null by default
happens at run time, not at compile time. This is compile time. We're actually doing the
development right here. This is compile time. It's not even letting me
compile the application. What we have to do
at compile time, it's just initialize
this to null. That way the error goes away and we can actually
run the program. But the compiler is
helping us out here. It's saying, look, this is null. You shouldn't really be using
properties on a null value, otherwise it's
going to fall over. But by tricking it, we've made that error go away. So I can show you an example of using something
which is null. Now, list is null. I'm trying to access a
property here called count on the null object list. Let's see what happens. Now an error has popped up here and it says null reference, exception object reference, not set to an instance
of an object. Now you'll see this
error a lot in your ventures moving
forward with C Sharp. It's just one of those things. But basically you can see here, our reference type is null. If something is null, we cannot use methods on it. We can't use properties on
it because it has no value, it has no memory
stored on the heap. It's pretty much just
an empty pointer of an object. There's
nothing there. It's null, we cannot use it. All we have to do is instantiate it and actually
give it something. Now if I run the application, you can see here the error
has gone away because we've instantiated the object
and it's no longer null. That's something to be very cautious on when
working with null. I think you get
the point of null. Now, for example,
if I have a string, let's delete some
of this stuff here. If I have a string, I'm
going to call it test. I'm going to initialize
it to an empty string. And what I'm trying to
say is an empty string, for example, is not
the same as null. We've talked about null. We know it's a null reference. What a lot of people do, they get a bit confused with null. They think it's just
an empty value, like an empty string. This is not true at all. And I can prove that to you if I just set up a bolen for example. And I have a condition
that compares this empty string right
here to the null value, and you will see
that it's false. What I'm saying here is
if test is equal to null, if an empty string
is the same as null, I can even write it like this, I don't even need a variable. Then print the value of
true if it's the same, otherwise false if it's not. So you can see there, null
is not an empty string. A beginner's mistake,
perhaps thinking that. But I thought, I'd
mentioned that null is not the same
as an empty string. Null is simply a null reference. An empty string is just
that, an empty string. I hope this clears
up what null is and how it's can a used
and why it appears. In our day to day lives doing software development.
Thank you for watching.
71. 17-2. Nullable Value Types: In this tutorial,
we're going to be talking about nullable types. What are nullable types? In our last tutorial, I highly recommend
you watch that. Where we talked about
the keyword null, I briefly mentioned
that reference type objects like lists and
objects and things, if you don't initialize them, they get the default
value of null, which is a null pointer. However, for value types, these tend to have the
default value of zero. But if we try to use the keyword null with
a value type object, it's not going to
work because we can't really give it
a reference pointer. Because it's a value type, it stores a value like
3,456 for example, or true. It actually stores the value of a value type in the
stack area of memory. So what is a nullable type? Well, a nullable value
type like these is an instance where a value
type can actually store null. So why would we want to do
that and how do we do that? So for example,
when I tried to set this as null before,
it didn't work. However, if I add a question mark after the
data type right here, you can see that error has
gone away, It's been resolved. What is going on here? Well, to turn a value type
object like an into ball, a character, simple types. If we add a question mark
to the end right here, then this represents a
nullable value type. Now this variable is a
nullable value type. Now it can take a value, or it can take the keyword null. Why might you want to do this? What is the point of this? Well, imagine you have, for example, a class register. You have a bit of
software and it marks the attendance for students
in your classroom. Now let's say it has a database attached
inside the database, you have all the names
of the students, First name, last name, all of that good stuff. And then you have a Boolean in the database and the value in the database would be called something like is in attendance. Now, if the children haven't even arrived to
the classroom yet, then we don't know if
they're in attendance. We can't really say true
because we don't know. We haven't actually
done the register, we haven't actually
checked to see which students showed
up to the class. But if I store the value of falls in the
database by default, then I can just change this to true if they are
present in the class. Well, I mean, this is saying
they're not in attendance, but really I'm not
sure yet because they haven't arrived
to the classroom. In cases like this,
you might want a third value for a
Bolen for example. You might want null
if we don't know yet. If the student arrives and
they're here, we can say true. But if the student is absent, maybe they're sick,
we can say false. So in cases like this, we might want a third value. And a key word like null represents something
like a default value, like not knowing the outcome
yet, or something like that. So if we're not sure
if they're here yet, then we could use something like a nullable data type here,
which is the Bullen. And we don't know if
they're in the class, so we can just
initialize it to null. And in the database for this maybe this field would be empty. Or it might even say
null. It doesn't matter. But the point is,
when the children start arriving into the class, then we can set this
to true and false. And that's kind of the
principle behind it. It gives you a third
option, for example. And again, this is
similar with integers. We can set those to
null if we don't have a specific value for whatever
number we want to model. So anything like that, there's lots of
different reasons why we might want a
nullable value type when working with
nullable value types by just adding a little
question mark after the type right here. It does give you a few more
options. And why is that? Well, let's take
this variable here, for instance. This is nullable. Now, if I put a dot afterwards, I have access to a couple
of properties here. If I remove that question mark, so I have a simple bolen, you can see those
properties have disappeared. What
is going on here? Why do I have these
extra properties for a nullable value type? That's because behind
the scenes it's a structure very
similar to a class. Rather than having a simple
boolene like before, where we can just have a
boolen and then use it. We can output it to the window, we can pass it to a method,
all that good stuff. We have a structure.
Think of it like a class. What the class
does in this case, it just exposes two properties. One is the actual value for
our nullable data type. This now is in attendance stop value would be the same as having a
non nullable data type and using that we can use
the value property here to get the underlying value
which would be true or false. For example, it has one other thing as
well called has value. Now we can actually use this Boolean property here to
work out if it has a value. What you would normally
do for something like this is have an if
statement and say, okay, does it have a value? Okay, It does have a value, therefore we can access the value and print it to
the console, for example. So something like this and doing things this way and
having these properties available to us
avoids things like null reference exceptions or just even checking
for null for example. This is why it has these
properties available. We want to check it has a value and then we can
utilize the value. This is why these
are quite useful. And this is why when you
define a nullable data type, it exposes these extra properties
for you to make use of, because it gives you this
third option which is null. If you were wondering
if you have a nullable value type object
and you don't initialize it, then the default
value would be null, not zero in this case. Because it's nullable,
the default value is null in a nutshell. That is an example of
nullable types in C shop.
72. 17-3. The null-coalescing Operators: Null coalescing operators in C sharp sound super
complicated. But what are they? Well, one of them looks like
this, two question marks, another one looks like this, two question marks
followed by n equals. But what are these random
characters you're typing? I hear you ask,
Allow me to explain null coalescing operators
allow you to work with reference types like this
list here, for example. Which could be null but
it might not be null. Also, nullable value
types which could be null or they might be
something completely different. Let's take a look
at an example here. So here I'm creating a
list of strings here, and this is called
shopping list. And this is going to contain all the items on
my shopping list. So I'm going shopping next, I have this type here, which is an integer and this
is the cost of my shopping. Now, I'm going to
default this to null because I haven't
been shopping yet. Now I may find the
time to go shopping, but I may not find the
time to go shopping. If I do go shopping, then the cost will represent
the value of my shop. However, if I can't be
bothered to go shopping, then it's going to
retain the value of null because I haven't
been shopping yet. Therefore, there's
no cost for my shop. Later on in the application, whether I went shopping or
whether I didn't go shopping, that doesn't really matter. But I want to output
a message that says my shopping cost was then
the value of the shop. In a normal world with a
simple data type like this, you perhaps initialize
it to zero and then, or it could have another value. For example, I run the program, it tells me the cost of my shop. However, if I create
a nullable value type like this and
initialize it to null, then I typically use the value property to
access the value here. However, if this
doesn't have a value, perhaps I didn't find
time to go shopping, then if I run the program, I have an error here. We've talked about this before. The nullable object
must have a value. You can see I'm accessing
this value property, but I'm not actually checking to make sure it has a value. What I typically do in this case is just have
an if statement here and check the has value property of this nullable
type right here. Now I'm saying if
I have a value, then I want to output the value. This looks like it should work. Now it looks like I have
nothing. But it's not crashing. At least it looks pretty good. But you can see every time
I try to access this value, I'm having to do
a condition here. I'm having to do an if
statement and actually check that there's a value there before I can
finally use it. Whether I want to output
it to the window, whether I want to pass
the value to a method, or a method of a class
or somewhere else. So basically I have to check
it before I actually use it. But what if I told you
there's a way where I can combine these
two things into one? Now this is where
I introduce one of the null coalescing operators, which is the two question marks. Let's take a look on how
I can simplify this here. I'm going to remove the
has value check there, and then I'm going to
remove dot value here. Then I'm going to
introduce one of the null coalescing operators, which is two question marks. I'm just going to use
zero as an example here, and I'm going to put
parenthesis around the whole thing so it
doesn't throw an error. What do you think this
is going to do now? Or perhaps you don't know, because I haven't
explained it enough. Let's run the software and
actually see what happens. I run the software now, it says the shopping
cost was zero. You can see, well,
the cost is null, but for whatever reason, it's outputting this zero here. However, if I change the cost of 4567 and run the application, now it's actually
outputting 4567. What is going on here? Well, this null coalescing
operator basically says, if this is null, so there's no value, then evaluate whatever is on the right hand side of
these two question marks. However, if this has a value, anything that's not null. For example, evaluate this side of the question marks and
ignore this side completely. Don't even evaluate this side. So this is how one of the no
coalescing operators works. And you can see we don't
need that condition there. It's wrapped up in a tidy little two character
statement right here, which is two question marks. So let me illustrate
that a little better, just in case you didn't
get it the first time. So let me create a method here. And I'm just going to
call it get default cost. So what this method
is going to do, it's going to return
a default value for the cost if no
value is specified. It's just going to return
zero with this operator here. I'm just appending a string to the result of whatever
this evaluates that. It's either going to
evaluate to the left side, which is cost, or the
right side which is zero. However, it doesn't
just need to be a zero or a simple variable. It could be the result of an
entire method, for example. Now if this is
null, which it is, it's going to evaluate
whatever is on this side. It could be a simple type, it could be a method. You see there's lots
of options here. It's called evaluating. If I run the application, now it's outputting zero. And just to prove
that it's actually running the method,
let's run it. Again, you can see
the right side is being evaluated because
the left side is null. That's the power of the
two question marks here, otherwise known as a null
coalescing operator. Here is the syntax here, the two question marks here. The usage is, you
have a nullable type, whether it's a nullable
simple data type, or it could even be
a list, for example, because reference types can be null, as you can see there. And then on the right hand side, we have something to evaluate
if the nullable type, which is this on the
left hand side, is null. We've talked about all of this, but this is a nice visualization if you didn't get
it the first time. This is one of the null
coalescing operators Right here. I want to introduce one more
null coalescing operator now that looks
something like this. It's two question marks
followed by an equal sign. And it's quite similar
to the last example, but it's to do with
assignment as well. So what does all that mean? Well, let's take a look
at this example here. I have a list of integers here. And this list will total
all of these expenditures. So all of the bills
I paid this month, all of the cost of the
shopping I've done this month, and the whole entire cost of spending my money
on useless things. So all of these
will get added to these totals here as
separate line items. It's a list, so I want to add each of these
totals to this list. So we can do that quite easily. We can make use of the ad method that adds this to the list, and then we can just put the
totals here, but remember, it's a nullable type, so we need to use
the value here, which looks fine,
but oh, wait, no. Now we have to check,
it has a value. We have to make use
of this property. Oh, yes. But that has to go in a condition here to make
sure it has a value. For example, then we
can add the value in. This should work, but remember when I said null
coalescing operators are shortcuts for all of this. We don't need all
of this at all. In cases like this, we can make use of the other
null coalescing operator, which is the two question
marks and the equal sign. What does that do and
how does that work? Let's say for example, these are defined as null here, for whatever reason
during our software, we're not really giving these any values, they remain null. Well, maybe one of
them has a value, but for whatever reason some
of them can still be null. We come to adding
these to the list, we only want to add the
values where they're not null because we can't add
null things to a list. Even if we try, it's
not going to letters. What I want to do is if these
have a value like this, for example, then I want
to add it to the list. This one has a value of 4567, so I want to add it. However, if they're null, then I want to add zero instead or some
other default value. Basically, I don't want to
add null because I can't. There is actually quick
way of doing this. What I can do is use this null coalescing
operator followed by a zero. Let's reset that. What that does, if this
variable here is null, then it's going to assign
zero into this variable, then add that to the list. If this is, if the
left hand side of this operator
evaluates to null, which it does because it's null, then this variable will receive the value of whatever
is on the right side. Remember, this could
be a simple value, It could be a method
that has a return. It can basically be any
expression that can be evaluated. So let's just put zero here. What we can do, we can do
this for all of these. We want to add all our cost
of the bills, for example. We want to, of course, add the cost of spending our
money on useless things. Now look what happens if I run the program and add
a break point here. Now I go down to my totals
here and expand that. You can see the list
has all the zeros here, which is the default value
as you can see here. Not only that, you can see this reflected in the
variables themselves, they now have the value of zero. To illustrate that point, I'm just going to change
one to something like this. I'm going to run the
software one more time. If I come to the locals
window down here, you can see this variable has actually
retained this value. It's been assigned into it, it now has a new value, 4567, and this is now
reflected in the list as well. This null coalescing operator to question marks in equals. If the left side is null, then the left side will receive the value on
the right hand side. That is how this operator
works. Just like before. I'll write a code comments, so you can see this
illustrated right here. If the nullable type
evaluates to null, for example, cost of shopping is null and
it's null at that point. Then evaluate whatever's
on the right hand side of this operator and assign
it to the nullable type. Obviously, if the
nullable type is null, it receives the value. Those are two null coalescing
operators in C Sharp, how they work and also
why they're useful. It's nothing you
cannot already do with a condition to
check the value, but it is a nice short cut to minimize code and also
development time.
73. 18-1. Named and Optional Parameters: I'm going to introduce a
couple of tips now that you can do when calling
methods in C Sharp. This is to do with passing
the parameters in. I'm going to talk
about what's called named parameters and also
optional parameters in C sharp. Let's look at this example here. It doesn't really do much. I have a sample method, it takes in various parameters, all of different types. We have a video game object, a couple of numbers, a string and also a booling. Inside the method,
we're just outputting the title property
of this game object, which we specify up here
in the constructor. Next we're adding
the two numbers together and
displaying the result. Finally, we have a condition. If the value of this
booling variable is true, then we're outputting
the message here. It's a bit of a
gauntlet of tasks. It doesn't really have any
purpose in the real world. It's just for the
purpose of this example. When we call the method, you can see we're setting
up a new object here. And then we're
calling the method passing in that object and also the remainder
of the parameters when I run the program. You can see it pretty
much does exactly what it says so far when
calling methods. We've been calling
these methods with the parameters in order
which they appear. The game object is First
we pass in the game first, followed by number
one. Number one. Number two, you can see
all in order which they're specified by using something
called named parameters. We don't need to specify
the parameters in order. Let's take a look at an
example of that right now. Say I want to switch the position of these
two parameters here, Hello, and also
the Boolean true. Now I want to specify
the bolen first. What we do, we take the
name of the parameter here and prefix it with a
colon, just like that. We're going to
specify that first, now we're going to
specify the message. Afterwards, we do
exactly the same thing. We take the parameter, we add the colon,
and then its value. Now I've traded the ordering
of these two parameters. In order to do that, I have
to specify the name of the parameter just to tell the system which one
belongs to which one. We just fix that
with a colon here. When I run the application, now we have exactly
the same result. These are named parameters. You can see we only changed the order of the
last two parameters. The first three remain
in the same order. That we don't need
to give these a name because they're in
the same order. However, if I want to name my first parameter and put it somewhere
entirely different, then I'm going to have to
name every single parameter. Otherwise, we're going
to get an error here. In this case, I don't
need to name the first three because they're in the exact same order
from the start. But if I move this game all the way to the
end, for example, and give that a name look
something like this, then I'm going to
get this error. And that's because I need to prefix everything
else with the name. Now you can see
the error has been resolved because game has
been moved out of position. And that was the very first one. Therefore, there's
no ordering at all. So they will all need a name. In this case, that's the
power of named parameters. But why is it useful? Well, you could argue it
improves readability. You could say from the
actual call itself, assuming this method
was locked away in a different class
or a different file, you only have this
visibility on your end, you can clearly see
look number one has the value of
this number two, as this it gives you a bit more information
about the call. However, it does create a bit more code in
your application. Another reason,
perhaps a developer is working on this method. Here, the method isn't
quite finished yet. They have maybe five
parameters for example, but maybe soon they're
going to add a couple more. Your job as a tester
is to test the method. You're testing the method
with these five parameters, but you don't know
if the developer is going to add
more of them later. So what you can do, you can use named parameters here to conduct any testing
you wish to do. When the developer then
adds two more in any order, it doesn't really matter, Then you know that your
parameters aren't going to be passed into different
ones by accident. For example, if
the developer then adds two more
integer parameters, then we know that number one and number two will be
5.3 in this case. If the developer adds
3.4 for example, we're not accidentally putting these numbers in those slots. In cases like that, it's quite useful when you're
not accidentally passing parameters of the same type to
different parameters. You're literally saying, okay, this parameter called this
will receive this value. That is quite useful. It's not only methods. You can do this in constructors and a couple of other
things as well. If I go to this video
game class where we've specified this parameter
to the constructor, you can see the constructor just takes one argument,
which is title. Just like when calling
methods, for example, I can prefix this with title and it's going
to compile just fine. We're not limited
to method calls with named parameters
like these. We can also use them in constructors and other
things like that. So let's talk about optional parameters now.
What does that mean? If you have an
optional parameter, then you can give the parameter a default value if no
parameter is specified. For example, let's look at
this display message Bolen. Right here, we're passing
in the value of true. Let's just say we don't
have to pass in a value. But we can, if we want to, what we can do here,
we can say, okay, if this parameter isn't passed into this method
display message, then let's just set it to
a default value of true. If the parameter is
omitted, it's not there. Then when this method
then gets called, it's just going to
initialize this to true. If this is true here, it's going to
output the message. We can take a look at that right now to see if that works. You can see the
messages being output. Similarly, if I change this
default value to false, then we're not going to
see this message at all. It won't say hello,
which it doesn't. When specifying optional
parameters in C Sharp, they have to go after
the required parameters. For example, if I make message
an optional parameter, I just initialize it to a default value of an
empty string like this. You can see I have
a little error here when I try and
compile the application. For example, if I just
set this to true, you can see there's an error. If we come down here, we can see this error here. Optional parameters must appear after all required parameters. All optional parameters
must come at the end. Here you can have as
many as you want. For example, we can make
message a default value as an empty string and also display message as a
default value of true. Then we can actually
remove these values. We can even go as
far as saying, okay, let's initialize
these two numbers to zero if they're
not specified. So you can see there, then we don't need these for example. But it really does depend on
your purpose and what you're aiming to achieve if we
run the application. Now we can see adding the
two numbers together, a zero because we're
initializing them to zero, because we're not
specifying the parameters. Pretty much the only thing we're doing is outputting the title of the video game here when we actually call
this method here. If we look at the
parameter list now you can see there's a bit
more extra information here. It requires a video game because this is a
required parameter. However, you can see
optional parameters now have these square
braces around. It also gives you the
default value 00, an empty string and also true. It does give you some
feedback on what is required when trying to
call this method as well. You can see how these
optional parameters are represented when trying
to call your methods. Again, you're not
limited to method calls. With this, just like before, you can use these in
constructors and again, some other things as well. Delegates indexes. If I set my parameter to the constructor as
a default value, as an empty string, then I no longer need this
value because it's optional. When we run the application, we're just going to
get an empty string. You can see there,
there's no game title because the default value
is an empty string. This is the power of
named parameters and also optional
parameters In C sharp. It opens up things to a whole
new realm of possibilities. I hope this tutorial helped
you and happy coding.
74. 18-2. The out Keyword: I'm going to talk
about the out keyword in C sharp and why it's useful. Consider this
example right here. This method, what it does, it takes in four parameters. What I want to do
is add these two together and then subtract
these two together. You can see I'm doing that here. I'm getting the result
of the addition in this variable and the result of the subtraction
in this variable. But how do I return
both of these? When we talked about
returns in methods, we can return a type here, but we can only
return one value. How would I maybe 235 different things out of
a method? Is that possible? Well, in short answer, yes, we can use the out keyword
in order to do this. And you see the out keyword
used in many instances. For example, a method might do some operations and
return a result. But we also want to return
maybe whether the method was successful or maybe a log of any errors that
happened along the way. We not only need the
result out of the method, but maybe we need
more information on how it handled things, you know, what errors occurred or pretty much
anything like that. So let's take a look at the out keyword and
how it's useful. Now the out keyword
on how it behaves, it's very similar
to the ref keyword. If you didn't watch
my tutorial on the ref keyword or passing
types by reference to methods, then I highly recommend
you check that out. What I'm going to do here, I've defined two
local variables here, result, add, and
results subtract, and I've initialized
them to zero. Right now I'm outputting
them to the window. Inside the method, I'm doing pretty much the
exact same thing, but I want these
results right here to reflect in these variables so I can output
them to the window, because right now I can't get these two values
out of this method. How do I do that? Let's take a look at using the out keyword, what I can do inside the
parameter list here. For this method, I can add an extra parameter
with the out keyword. What I want to do,
I want to return both of these values
out of the method. I'm going to have two
out variables here. The first one is going to be
the result of the addition. The second one is going to be the result of the subtraction. Now, because these are
getting passed into the method with their
own types and own names, I can't then give them a brand
new type. I remove those. That is pretty
much how it works. Now you can see an error
has popped up here. And when I hover over that
saying there's no argument given that corresponds to
the required parameter, basically I need to specify
two extra parameters. The number of parameters
matches the definition. Here, I need two more. When you have the out keyword in the method declaration here, you also need to specify the out keyword when
calling the method. This is what I'm
going to do here. If you watched my video
on the ref keyword and passing value types and
reference types to methods, you'll know that when we pass something to a
method by reference, we can modify the values
inside of the method and we're referencing the area of memory where
these variables sit. This is what the
out keyword does. But there is one subtle
difference between the ref keyword and
the out keyword here. That is, variables
don't have to be initialized before
passing a variable with the out keyword. What do I mean by that? Well, let's actually see if
this example works First, before we get ahead
of ourselves, I'm passing in 20 values
as out keyword parameters. They're coming into the method, and then we're actually
setting the values right here. Let's take a look. You can see we get the expected result. Two plus two is 4.6
minus four is two. It does work. And
we're actually getting both results of these
returned out of the method. But it's not really
returning out of the method, it's just modifying
these two valuables as they're being passed by
reference into this method, then we're just
outputting the results. I said before, there was one
subtle difference between the out keyword and
also the f keyword. And that is that when
using the out keyword, variables being passed in do
not have to be initialized, that means they
don't need a value. It's still going to work
when I run the software. Now you can see
they have values. And that's because
when things are passed into a method here, we need to give them a value. If we don't do that, we're passing in a variable. Here you can see there's an
error and it says result ad must be assigned to
before the method finishes. So we need to actually do something with these
out parameters here. We need to do
something with them, give them a value,
initialize them, do something that is the subtle difference
between out and ref. But generally, the out
keyword allows you, in a way, to return more than one
item from a method, and that's its main power. Really another thing, we don't have to define our
variables here. We can actually define
them all in one line. If I remove these
variables completely between the out keyword and
the variable I just type in, int, for example,
for the data type. Now we're actually defining our variables in one
line of code here. And you can see it
looks a lot idea. So we're defining them here, then we're passing
them in all in one. And then it's doing something, throwing them back out. And then we're
outputting the results. So you can see we get the
same results right here. So that's the power of the
out keyword in C sharp.
75. 18-3. The in Keyword: I'm going to talk about
the keyword in C Sharp. Now, I have a very
simple example. Here I'm calling a method that
adds two numbers together. When the method is called, we're stuffing the result
of these in a variable, and outputting the result
by adding two plus two, we get the output of four. How does the keyword
come into this? Well, when we use the
keyword in a method here, we can specify this before
any parameter we wish to. For example, number one, what the keyword does, it prevents us from
modifying this value at all. Then if we try and say
set a value like that, for example, you can see the
software won't even compile. When we highlight this
and hover over it. It says cannot assign variable int because
it's read only. It actually prevents us from doing anything with
this variable. Here again, we could put this on any number of
parameters we wish to. These are simple value
types, simple integers. Let's take a look at how
this works with objects. For example, you can see here I have an example
with an object here, like video game for example, I'm setting the title of the
game through the constructor to Minecraft and just
outputting the game's title. But if I try to
modify this object in any way when specifying
the in keyword, then it's going to throw a
similar read only error. You can see here I'm erasing the title by setting
it to an empty string. But it's saying it can't be
assigned to, it is read only. Similarly, if I try and create a new instance from
this completely, then I have exactly
the same error. This is the power of
the keyword in C sharp. It prevents things like
methods from accidentally modifying any of your parameters which you wish to pass in. If you know this method
is not responsible for modifying your
parameters in any way, then you might want to
consider specifying them with the in
keyword to protect your data and avoid
methods from changing any of your data and having
unexpected things happen, which can happen quite
a lot, believe me. But the beauty of
the keyword is yes, you could pass a constant or a read only variable in
here, for example. But maybe your objects aren't
read only or constant, but you just want to
make them temporarily read only just for the
duration of the method. That is the point of
the Q word in C shop.
76. 18-4. The params Keyword: The Perms keyword in C sharp. It looks just like this and
it's short for parameters. But what does it mean
and what does it do? Let's take a look
at this example. Right here I have a method that adds some simple
integers together. It takes four parameters, it adds them all together, and outputs the result. The method takes them in
from whatever's calling it. We're adding 224.5 Let's
output the result. There it is there. For example, if I want to add two
numbers together, maybe I want to add
three numbers together. Or maybe 17 numbers together. But I want the same, I only want one method. I want the same method and one method to add all of
these numbers together. How do I achieve that? Well, maybe I could
create a custom object, for example, feed
in all the numbers. Or maybe create a list and add all the numbers to the list. Then I can pass the
list to this method. Essentially, that's what
the prams keyword does. In this case, when I
use the Prams keyword, I type in Prams here into
the method signature. Here it is a parameter itself. Next I put the data type. The data type can be pretty much anything behind the scenes. It uses the object data type, which is what all data
types derive from anyway. But we're using integer. We can use custom
objects if we wish. Custom instances, it
doesn't really matter. I'm just going to call this list because this list is going to contain all our numbers that we're passing
to this method. Now when working with lists, we're going to use
something like a loop to loop through every
item in this list. So we can add all the numbers together. Let's do that now. We initialize a
variable to zero. This will keep a tally of all the numbers that
we're adding together. That should work right there. We're looping through
every number in the list. We're keeping a running tally, adding everything to
this result here, and then outputting it. We're going to get
the same result Here, you can see 13. Now this is the power
of the params keyword. Watch this. Okay, I've modified the calling
argument here to add a lot more
parameters to this list, but you can see it hasn't
caused any problems. This is the power of
the params keyword. If we were to build up
a list, for example, and pass this into the method, then we would have to modify
the list in this way too. But you can see how this doesn't
cause any errors at all. We can compile the software
and we can run the software, and we have our expected
result right here. This is the power of
the params keyword. It allows us to use
one method to accept a varying number of
parameters of the same type, and then it can work
with that information. Now, there are a few rules
associated with this. There can only be
one params keyword per method declaration,
for example. We can't have two of these like, so it's not going to work. Secondly, the params keyword must come at the end
of everything here. If I have more than
one parameter here, params must be at the very end. It can't be at the start, it can't be in the middle. So you can see an error
has occurred here, because it must be at
the end of the list. And lastly, the params here must be a single
dimensional array. It can't be a two
dimensional array, It can't be anything
weird like that. So there's some of the rules associated with the
params keyword. So that is the power of the
params keyword in C sharp. Yes, there are other ways of
achieving the same results, but the more tools you
have in your toolbox, the better developer
you will become. So that's the params
keyword in C sharp.
77. 19-1. Enumerations - The enum Type: I want to talk about
enumerations in C Sharp, otherwise known as enums. And the keyword looks
something just like that. But what is an enum and
why should I use it? Well, I have an
example right here. Here I'm setting up four
video game objects. They take in various parameters. Let's take a look
at the class now. So you can see it
takes a console, a video game title, a video game publisher,
and a rating. So let's pay attention to this
rating string right here. What I want to do,
I only want to allow certain ratings
for everyone. Ten plus teen, mature, 17 plus, et cetera, et cetera. I only want these
values to be passed in and I only want to
deal with these values. But when setting
up these objects, you can see I'm
putting them in here. But it's very easy
to make a mistake. I could make a misspelling, maybe a lower case,
something like that. If this application is
connected to a database, then there's a bit of trouble. I'm going to be storing incorrect values and the whole
system can get messed up. If someone wants to search
for a game, for example, and the rating is wrong
because it's been spelt wrong, then perhaps if they're
searching by rating, this video game might never
come up in the search. Lots of reasons why we need our data to be
concise and accurate. One way we can tackle this
problem of making sure that there's no
spelling mistakes for this string variable. Rating, for example, is to use something called an
enum or an enumeration. How do I set that
up and how do I integrate it into my
video game class here? Well, let's take a look. Let's come over to
the right hand side here where we have our project. We're going to write Click, Go to Add, and then go to class. We're going to call this something that
represents our rating. Now if we have a very
large piece of software, we might want to be really
descriptive with this. I think maybe video
game rating is good. However, sometimes when
you create an enumeration, you might have a class with
exactly the same name, and you can't create a
class with the same name. What a lot of people do when
creating an enumeration is to add the word state
or type afterwards. So every time they create one, it either ends in state or type. It's really up to you,
it doesn't matter. But I'm going to call
it something like this. So pay attention here, you notice it's a class
here when I click Add, so if we come over to the left, now we have an internal class
video game rating type. Well, we don't want a
class, we want an enum. And there was no
template for that, so now we have an enum. It's as simple as
changing class to enum. We have an enumeration
right here. So how does this work? Well, let's go to
our video game class here and take our
allowed ratings. I'm going to put them in here as a comment so I can
reference to them. And I want to create an item in the enumeration for
each of these ratings. So I want everyone
ten plus teen, mature 17, et cetera. So I want all of these
items in this enumeration. And the enumeration
is like a list. So like a list of values. And this list isn't just a list, but it's like a read only list. We can't modify
this information. It's pretty much read only, so we use it to refer
to these values. It will all become
clear momentarily. What I'm going to do is create some values for each
of these ratings. In the enumeration I'm going to start with which
stands for everyone. Once I've created one value, I put a comma and
then a new line. Now I can do the next one.
Now there's a problem. Once I've typed in ten, that's because in enumerations, your items cannot contain numbers or certain characters
like this plus symbol. We're going to have
to type this out. In this case we
can say ten plus, and that works just fine. Let's continue. I've typed out a rough enumeration
here you can see we have all of these values reflected
in the enumeration. We can add more at a
later date if we wish to. Now, how does this work? How can we put this
into our class? Well, this is now
like a data type really where we had a
string rating before. We can use this
enumeration right here. If we go to our
class right here, we replace string with
video game rating type. We also replace it
in the parameter and also any methods we may
have here. Also there. And it looks like we
have one problem, and that's due to accessibility. By default, our
class is internal, but because our video
game class is public, we need to make the
enumeration public as well. Now, all those errors
have gone away. Now, we've actually changed the parameter to
our constructor, to an enumeration type. Let's have a look how we
construct these objects now. Now you can see there's errors on all of these right here. Let's try to change this teen
one to use our enumeration. If I put a comma here, you can see the intellisens, the autocomplete has
chosen our number for us. We're just going to
double click that. Then we're going to put a dot. Now you can see there's
a nice list here. If someone wants to
construct these objects. Now they can't just
put in any value. Look, it requires a
video game rating type. You can see in the
parameter list. But now we just
can't put anything. We have to choose
something from this list. If we don't, then
the application won't even compile
because there's an error. You can see how this enumeration forces us choose an
item from this list. Now we can say
teen, for example. Now if we replace each of
these with the enumeration, you can see when we're
constructing these objects, now it's going to look
something like this. You can see this
is a locked idea. But not only that, it
forces people or pieces of software or anything else to not make mistakes
in our information. You wouldn't really use
this for something like maybe Blizzard or
World of War Crafts because these are unique. However, perhaps the
console could represent an enumeration because there's only a finite
number of consoles. You know, you have the
Playstation X box or PC. So this again could be
represented by an enumeration, but for something like rating, this seems like a perfect
candidate to have as an enumeration when
working with enumerations. For example, maybe
these video games are stored in a database. Now, this database will
have the video game name, the title, and it might not have the enumeration full
name in the database. It might have an
integer like 01 or two. Each one of these
integers might represent a different rating
in the enumeration. For example, every one would
be 010 plus would be one, teen would be two, et cetera. When you define enumerations
in visual studio, there's an underlying type
that means in the background. By default, each one of these has a value
which is an integer. And I'll show you
what I mean by that. This output one of these enumerations to
the console window. I'm just going to output
video game rating type teen. It's probably just
going to say that on the window itself,
it just says teen. But watch what happens if I
convert this to an integer. So if I run the application, now you see it has
the value of two. By default, there's an
underlying integer in here. That's because by default
the first item is 012345. This is done by default. It's default behavior, but you can actually change
that if you wish. You can specify your
own values for these. By default, it looks
something like this. Everyone has the value of zero. This one has the value of 12345. This is what it looks
like behind the scenes. These have these integer values. You can reference them with the number or you can
reference them with the name. The choice is up to you. But typically, when you store something like this
in maybe a database, or you're passing these values to a different
piece of software, then perhaps you will be sending the integer just because it's smaller and it's
easier to work with. This is why enumerations
have an underlying type. Consider this as like
an index for example. But like I said,
you can configure your own types but
also your own values. For example, I want
this one to be ten, that one to be 2030, 40, 50. It doesn't really matter, the choice is totally up to you. And now if we output this
again to the console window, you can see ten now
has a value of 22, and that's because we
gave it the value of 22. I don't know why we did that, but you can see that's
how the principle works. So basically behind the scenes, it uses an integer, but you can change this to a different data type if you wish, like a byte or a long
or something like that. The choice is really up
to you, but by default. It looks something like this. If you want to change the type, you can add a colon afterwards
and put the new type here. When you have a type here, then all of these values must follow the
type you specify. Perhaps this might be something you don't use immediately, but it's always good to
have this knowledge in your mind for when you want
to apply it at a later date. But these are the possibilities and things you can do
with enumerations. What is also quite common is if you have an enumeration,
for example. All of these are
video game ratings. You might not want
to specify a rating, but the user, they're given
a choice of six options. But what if it's optional? So what a lot of
people tend to do, they'll define an item called non and usually give
it a value of zero. Or they might give it a value of 999 and put it at the
end, for example. But this is just an example of how you can make it optional. Non would be the optional
field in this case. If it's not mandatory, otherwise you can select
a rating right here. Again, that's just reflected by choosing the non
item from the list. There's no rating for this game, in which case it's optional. Now, enumerations. There's a lot more
to enumerations, and you can do a
lot more with them. There's a static class
called enum inside here, you can use various methods
to do with your enumerations. You can get the underlying type like the integer we
talked about before. And you can do various things. So we've kind of just
scratched the surface here. But what I will mention
is one thing to kind of keep your projects
a little more organized. If we come over to the right here and right
click our project, and what I tend to do is add
a new folder right here, and I usually call this enums. Inside this folder, I put all of my enumerations just
so they're tidier. So that way because they have the same file
extension as a class, then you don't
really get confused. You can hide away all your enumerations
in an enum folder. If you remember when
we talked about interfaces in the
interface tutorial, how they have the
interface keyword and not the class keyword, then you can create a folder
for your interfaces as well. This is quite common.
It just keeps things organized simply because they have the same file extension. If you have a very
large application with hundreds of classes, you can easily find your enumerations just because they'll all be in a
directory called enums, a nice bit of organization when working with interfaces
And also enums, enumeration is very useful. It prevents any misspellings
or anything like that. And it's very useful
when you have a finite list of items, for example,
consoles or ratings. Maybe when working with
suits in a deck of cards or representing months of the year or
something like that. But remember, enumeration items are read only like constants, so you can't assign
anything to them, so consider them as read
only when working with them. So that is enumerations in shop.
78. 19-2. Recursion and File Handling (File IO / System.IO): I'm going to talk about
a brand new concept now. And that concept is
called recursion. If you're familiar
with computer science, or maybe you've done other
programming languages, or even mathematics. Maybe you've heard of this word before, but maybe you haven't. So why am I on Google?
I hear you ask. Well, when I started my
programming ventures, recursion was something
that really confused me. Have you ever seen
the movie Inception, where the guy goes to sleep
and then he's in a dream, but then he goes to
sleep in the dream. And kind of plays with your mind and you kind of
wondering, is he dreaming? Which layer of dreaming is
he in or is he awake again? You know, it's very confusing. And the nested dreams
in this movie always reminded me of the concept of recursion and you'll see why. But hopefully in this tutorial, I'm going to break it down into simple steps so you'll
understand it a lot easier than I
once did when I started learning. And
I'll show you why. If you Google the
term recursion, you get a description here. The process of
defining a problem or a solution in terms of a
simpler version of itself. For example, you can
define an operation, find your way home as
if you are at home. Do you see what I mean here? It's not very clear, is it? And the more you scroll, the more confused you get. It's just one of those
things that you kind of pull your hair out over and
when you look at the images, well, the images don't
really help either. You just get this kind
of picture over here of something inside something else and it's just repeating forever. So let me explain to
you what recursion is. It helps by looking at
recursion in C Sharp in Google, and it gives you a
better explanation of what it is in
terms of C Sharp. Recursion is a concept in
which a method calls itself, and it is exactly that. In the world of C sharp, you define a method and the
method then calls itself. Now, why would a method
want to call itself? Well, if you have functionality inside a method to do something, then maybe you want
to reuse that code. Why not? Programming is
all about reusing code. It saves time, it's
easier to maintain, and there's lots of other
reasons to do that. This is what we're going
to be looking at today, recursion in C sharp, and we're going to define a
method that calls itself. We're over here
in visual studio. Now what I want to do is set up a method
that calls itself. If you watch any other
tutorials on recursion, you'll probably see
something where you have to work out the factorial
of a number four. Factorial is one times two, times three times four. And then you set up
a method to do that. I think that's quite a
weak and boring example. I think we can use something maybe we can apply
in the real world. I think a search feature
is really good for that. What I want to do, I want to introduce you to my very
bad music collection. Here you can see
it's quite eclectic. We've got all
different genres here. What I want to do is specify a search term and
that could be any, it could be a band name, it could be the name of a
song, anything like that. I want to return all of the music files that
match this criteria. So we're going to ask the
user for a search term, the user will type it in. The result will be
the full file paths of all of our music files. Now this music collection
is very unorganized, hence why we need a
search feature here. I have a music folder here, and inside that I have a folder called even more music in there. I have all these new folders, and then I have music
dotted everywhere. I think a search feature might be something good
for this example. The problem, I need
something to get the directories
inside a file path that I provide the software. So if I provide the software, this file path here, I need it to get
the directories. The second thing I
need to do is to get the software to get all of
the files in a directory, and check in turn each one of these files to see if they
match the search criteria. It needs to do two jobs. And why is this scenario a
good example of recursion? How can I apply a recursive
method to this example? Well, I want to get
the directories and the files for each
directory in here. I want to do the
same logic in here. I want to get these
directories, these files. And then inside these
directories, I want to check it. There's more directories
then also get the files. The methods logic pretty much applies to any
directory in here. I want to reuse
the functionality. I want to use it here initially. Then I want to dig
inside these folders. Keep digging until
there's no more, and then check the files here. Recursion will be a
very good example of something we can use for this
particular scenario here. Let's have a look
how we can do that. I'm over here in
visual studio now. What I need to do
is create a method. And the method is
going to call itself. And the job of the method is to essentially search for a file
that the user specifies. Let's set up that now. The first thing I
want to do is ask the user for a search
term. Let's do that. Then I want to accept
the input from the user. Now I've got the search
term from the user. I want to call a method. Let's set up a method that's actually going
to do the searching. I'm going to call
the method search. I think that's a
pretty fitting name. Now, I need to define
some parameters. What parameters should it take? Well, the first one,
we need to know where the music is located
on the system. We need a file path. I think that's a pretty
good first parameter. The second one probably
the search term. We need the method to know what we're actually
searching for. The last one, perhaps
a reference parameter and maybe that's a
list or an array. This is going to collect
all of our results. When you search for something, you might have one result, you might have no results. But you also might
get ten results, like ten matches
for your search. We can't just return
a simple type, we need to return something
like an array or a list. For example, I think using a collection such as a list
here will be quite fitting. I'm going to call this
results because it's going to contain all of our results
that we find from our search. Now we have the path
where the music is. We have the search term of
what we're searching for. Now we have a collection here that's going to
store our results. One thing you may
wonder is, well, why don't we have this
as the return value? Why do we need a parameter which is a reference type
like here for example? Well, the truth is
it doesn't really matter if I set this
as the return type. I think it might complicate
this example a little more. What I want to get across to
you is how recursion works, where a method calls a method, otherwise known as
a recursive method. If I set up a return type, then I have to return
the value out of each call to the
method within itself. I think it might complicate
the example a little. I'm going to use a
parameter for now, then when I've actually
developed the solution, I'm just going to switch this to a return type so I can show
you that example as well. That's the reasoning
behind it here. It's just going to
store the results. When developing recursive
methods like this one here, it's always good to get the
base functionality first. And that is what
it's designed to do ignoring recursion
completely. That's where the
method calls itself. What I want to do is use the path that's
given to us and use the search term and
see if we can actually get some results from
the root folder here. For now, we're going
to ignore digging into folders and
everything like that. What I want to do is
get these files here, get all of the files for the given directory,
And then in turn, I want to check each file to make sure it contains
our search term. If it does, I want to add it to the result list that
we've just created. Let's take a look how
we can actually get these files for a
directory and then check each title to make
sure it contains our search term back
in visual studio. Now if we want to work
with files, directories, file path, or
anything like that, there is actually a
name space we can use. This is provided to us. We use the using keyword
and then type in system and then O stands for input output. It's pretty much anything
to do with files logging to text files reading from
files, all things like that. It's a really useful
namespace that we can use. It's not included by default. For example, before in a
previous tutorial where we use the math static class and within math we can do
various math functions. This is included by default because it's
quite a popular library. When you create an application, you may wish to do a lot
of things to do with math, for example, and many
other things as well. However, not every piece of software you create is
going to work with files. This is why we have to manually explicitly include this library. That's just a bit of
information there. If you wish to use any other
namespace for that matter, you can add them below within the system
I namespace here. There's lots of
things you can do. You can do all of
this stuff here. Lots and lots and
lots of things. But there are a
few static classes you may wish to
be made aware of. The first one, for example, is Directory, and this
is a static class. Using this, we can
create directories on our system just by giving
it a path as a parameter. We can delete directories. We can get files within a
directory that we provide. We can do lots of things
to do with directories. This directory, static
class, is really useful. Another one is a static
class called file. With file, we can create files. For example, if we want
to create a log file, we can delete files. We can check if files exist, we can move an open files. So lots of different
things to do with files. The last one that's quite useful is the path static class. Path is really useful
for working with paths. If we're giving our file path, we can get the file
name from the path. We can maybe get the
extension of a file. We can actually work with a full path and we can
also join paths together. This is really good for
working with directory paths. There are three
static classes that you'll find really
useful moving forward. And we're going to
utilize a couple of these today when we develop our
recursive function search. Here, I mentioned before
that we want our method to get the files in the route directory
just to start with, just to make sure it's
actually working, what we want to do is get all the files in a
given directory. We know this information
because this is the path which is
passed into our method. I want to get all the files
within this directory here. To do this, we make use of the directory static class and there's a method
called get files. Get files takes
one parameter and that's the path where
the files are located. Now the return from this
method is a string array. Now this array will contain the full file paths for every
file in this directory. If we come over to
our music canal, it's going to get all
of these files here. Each item in the array will
contain the full file path. The full path on the system, that's going to be the return from this method, get files. I'm going to store that in
a variable called files. That's going to be all the
files in the given directory. Now what I want to do
is loop through all of these files here and
check that the file name, not necessarily the whole path. We just want to check
the file name to check that the file name
contains our search term. Here we need some loop here. I think for each loop
might be sufficient. In this case, visual studio has kindly given us some
autocomplete help here. I'll take it now. In this four loop, I want to
check each file in turn and check that the file name of this file contains
our search term. How do I do that? Well, when I want to check, I
need a condition. I know I'm going to need
an if statement here. Now, what condition do I
need in the statement? Well, I need to get the
file name from this path. I don't want the drive letter, I don't want the folder names, I only want the file name
when working with path. As I mentioned before, a static class called Path
is very good for this. There's a method called
get file name without extension which will get
the file name, say three. There's also one
called get file name. You can choose which one you wish depending on whether you want users to search for
file extensions as well. I'm just going to use this one. It takes one parameter and
that's the path from this, this highlighted code here. This is going to get the
name of the file without the extension coming
over to our music. It's going to get this
highlighted section right here, which is great. That's what we want to check
back in visual studio. Now I know that that
is the file name without the extension
and without the path. I want to try and see if any of that contains
our search term. In a previous tutorial, I covered working with strings where we did various
things with strings, substrings, and
things like that. Because this is a string here, path get file name without the extension
returns a string. Therefore, this will
represent a string. When I put art
after here we have all these different things
we can do with strings. There's a method here
called contains. Contains. Takes one parameter, which
is either a character, a string, or actually
numerous parameters. A character and a
comparison type. But we just want to use
this string overload here. We want to check to see if
it contains our search term. I think that is a
pretty good condition. Now, there is a bit
of a gotcha in here, which I'll reveal
a little later, but for now I'm
going to leave it. Now, we're checking to
see if each in turn file contains our search
term. That's pretty good. Now if it does actually
contain our search term, then we want to add
this path here, which is file, to our results
list. Let's do that now. We use the add
method to do that. We add the file there. If you don't know
anything about lists, then I have done a
tutorial on that. I recommend you check that out. Now it looks like we're
doing something pretty good. We're looking at all the
files in the given directory. If it contains the search term, we're adding it to
the result list here, Because this is a
reference type, it's going to remember
what we've added to it when this method has
finished executing. That is because it's
stored on the heap, it is a reference type. Now what I want to do is
actually call this method. Provide parameters to
it. Let's do that. Now. The first parameter I need is the path where
the music is located. Let's get that. Now,
put that back in here. This is the route directory where all the music is located. The next parameter we've
set up is the search term, which we take from
the user's input. The last one we need to provide a list where we're actually
going to store our resorts. I'm going to define a
local one here to Maine. Set up a new list here. I haven't given it
any capacity because we don't know how many resorts
there are going to be. Just created an MT list here. I'm going to pass
this into the method. When the method has
finished executing, we have access to these
results down here. That is because as I mentioned, it's a reference type. Now what we want to do is just display the results to the user. We could maybe use a four
each for this as well. What I want to do, every time we have a result in results, I'm going to say let's
just output the result. Then I could add like an if statement saying
if there's no results, maybe I'll print the
fact there's no results. Okay, so it looks
something like this. Now I appreciate there's
more elegant ways of doing pretty much everything
in software development, but I try to write this in a
way that you'll understand it's more easy to take in because this is
just how brains work. Perhaps at the end, we can
tidy it up that is optional, But what I want to get across is the principle of
recursive methods. We have some base functionality here when developing software, we can test, just to
make sure it works, we don't have to completely finish developing the software. I think now might be a
good time to test this, just to make sure it works. Let's run the application now. Now, please enter a search term. Let's try searching
for Aba, for example. Why not I go in my application, I type Abba says there's no results for
my search. Why is this? Let's try and figure this out. I go back into the software now, I'm not getting any
results out of here, but clearly I'm
adding a result here. What is going on here? Let's see if we can
figure this out. Let's put a break
point here and run the software. Type in Ab. What do we have here? It looks like we're getting
all of our files here. Are we actually reaching this break point
where we're adding the value? It looks
like we're not. So there's something wrong here. We can't seem to
get the file name properly or something quite
different is happening here. It looks like I've accidentally put path here when
we should have file. At the moment, we're only searching the file
path where the music is located and not actually the file name which
is inside the loop. If that resolves the problem, okay, it looks
like it's working. Now as you can see,
nobody is perfect. Mistakes happen,
but if you watch my tutorials on debugging
and everything like that, you'll know how to fix
problems yourself too. So it looks like it's working. Let's try something
else real quick. I did allude to a
gotcha earlier, and that is if I
search for Aber, where it's lower case I hit, and it says there's no results. But clearly we have
a song called Abba. What you can see here is
there's a case sensitive issue. That's because Aber in the
NP three is upper case, but we're using a lower
case search term. So how do we get around this? Well, file is a string and
the search term is a string. When we use strings, we have lots of things
made available to us. What we can utilize is this
method here called to lower. What that does, it converts
all of this to lower case. Similarly, we can do
this on the search term. Now we're comparing all
of our search term, all in lower case, to the name of the file, all in lower case. Now, we shouldn't have
case sensitive issues. If I run the application
now and search for Aber, you can see now I
have the result. Now we're ignoring case.
That's pretty good. I'm going to do one more
search and just search for maybe the letter E just to make sure we get
multiple results. Coming back, it
looks pretty good. It looks like we're
getting all the file names that contain the letter. That's pretty good. Now, I think we're ready for recursion. We have the base
functionality working. We're happy it's working
for the base directory. Now we can introduce recursion. The problem is
when you introduce recursion from the start, especially if you're
not proficient, then if you have an error, it could be with just
your core functionality. It's really good to
get this working before you introduce
the recursion to this. It makes things a lot easier. Let's introduce some
recursion into this method. Now, I appreciate you may
not get this the first time, but don't worry, you
will get it eventually. There's a few ways we
can tackle this problem. What I want to do, I have this search method
that gets the files, which is pretty good. But also, I want to
give this method the next directory in
the current directory. Here, for example, we
have our music directory. We're already
checking the files, but I also want to get all of the directories here as well. Then inside each directory, I want to do the
core functionality, which is to get the files, but I still want to get
the directories too. Then inside here, I want to do the same thing, get the files. Are there any
directories in here? Clearly, I need some
function to get all of the directories in the current
directory. Let's do that. Now, I'm going to
put that up here. There is a useful thing we
can do to get directories, and that's using the
directory static class. There's a method called get directories and it takes a path. What path does? It
takes our root path. And just like before, it returns a string array and each item in this array will be the full path of the directories
in this path here. So I'm going to call that
DR's for directories. And because we know that we want to go inside
each directory, we need to loop through this as well without even
thinking about anything. We know we need
directories and we know we need to check
each one without even worrying about the
problem of recursion or inception or whatever
you want to say. We know we need this
functionality now. Once we have this
functionality in place, we have to work out how to actually deal with this problem. What do we put in here? Do we need anything here? Do we need anything
here? Et cetera. But now we have a
bit of a template. Let's have a look at how
to approach this problem. I'm giving the root
directory to the method. What I might do
in this situation is get all of the directories. And with the first
directory I go inside it, then I call the method again, What it's going to do is
exactly the same thing. It's going to get all
of the directories and go in the first one. It's going to get all of the directories go
in the first one. And now we're in
the final folder. There's no more directories, so we can't go in the first one. So the last thing we need
to do is get the files. So what we're doing here, we're getting the directories always going in the first one, always going in the first one. Until we've reached
the very end, we get the files, we go out one, go in the next one, get all of the directories
go in the first one, get all the directories, go
in the first, et cetera. So that's what we're doing here. We're diving to the very bottom, which is the first
thing we're doing. We're going inside,
inside, inside, until the biggest dead
end which is here. And then we're
checking for files. So that's what we're going
to replicate in our method. Now the first run
of this right here, the search method,
we're passing it the path which is
the root directory for our music right here. What I want to do is get all of the directories like I just
mentioned in the root folder. That is all of those here. That's what this
four loop is doing. The first iteration of the four loop will be
this directory here. Now we want to actually
go inside this directory. What we can do, we can pass
this method to itself. We can call the
method from itself. Even what I want to do
is call the method. Let's simplify this.
Results will never change. We're not defining
any new results, we're simply just
appending to results when we have a result,
When we have a match. We're actually initializing
and defining results up here every time we
pass results around. We just want to simply
pass it around. When we call this
method inside itself, we just want to pass
this value inside. The only reason that we want to do that is just to add to it. We don't really
need to do anything special with this here. The same applies with
the search term. We're not changing the
search term in here, we're pretty much asking
the user for a search term. As far as we're concerned, it's pretty much read
only inside this method. Again, we're just passing
this through as well. Just like results, the only
thing that really differs here is the path within
our first directory. We actually want the directory
that we're going inside. It's going to look
something like this. If I just remove that a little, this is what it's
going to look like. I don't know if you can
wrap your head around this, but the first time this is run, we're getting the directories. We're looping through
those directories. So the first directory, we're calling this method again. Now this method is
being called with the first directory
in the original path. Once it's inside that
directory, again, we're getting the
directories again until we reach the very
end, which is here. Imagine this is the path
being passed in Now, now there's no directories. This is going to have
a count of zero. This for each loop
isn't even going to run because if there's no
directories in this result, this will be skipped entirely. Now when this is skipped, this method will not
call itself because this is the only time
the method calls itself. What it's then going to do
is get all of the files. It's then getting these
files here and checking to see if we have a match
and then the method ends. When the method ends, we go back to the previous call, which is inside this loop. Then it's going to call itself again on the
next directory, on the next iteration
of the loop. Then it finishes, goes
into the next directory. Here it checks for directories
and files. Does this work? Let's take a look, why
not enter a search term? So what I'm going to do, I'm going to give a search
term for a file like this one. For example, hello, hello. Now, hello, hello is
located in this folder, inside this folder, and hello, hello is not in the
base directory. By searching for hello, I know for a fact that it's checking quite a lot of folders in order
to find this file, that's a suitable
test I could use. Let's run the program. Please
enter your search term. Let's type hello in here. It looks like it's found it. You see this result,
searching for subdirectories, it's gone inside two directories and it's
finally found the file. Here, it looks like
it's actually working. This is an example here
of a recursive method, that's just a method
that calls itself. We're just stuffing results into a parameter which is a
reference type, it's a list. Let's do one more test just
to make sure it's working. I'm going to take
that Hello file, which is in here, and paste
it in a few more places. I'm going to put it here. I'm going to put it here. I'm going to put it in here. Now we should get a
lot more results. Let's run the program,
type in hello. And now you can see
I've found all of those instances of
that hello P three, so it looks like it's working. So that's pretty good news. Now the thing when writing
recursive methods, you need a way to escape
out of the recursion. The recursion will not stop unless you introduce
something like a condition, perhaps an if statement. Or maybe in our
case, we have a loop that loops through
directories and files. We don't have
infinite directories, we don't have infinite files. So eventually this
recursive method will stop. However, it's quite easy to have a method call itself endlessly, like in this example. If I have this method call itself with the same parameters, there's no way for this to exit. This is the danger
of using recursion. When writing recursive methods, always check to
make sure you have a condition or some
escape clause. Otherwise your application
will crash freeze, and you'll have a lot of unexpected behavior you
see if I run the program, now I type in any search term, you can see we have
a stack overflow. It tried to call itself
24,000 times before it eventually crashed because the stack is full of the
stack area of memory. Always be cautious of this when writing recursive methods. So at the start of the
tutorial, I said, oh, we could easily have this
collection here as a return. We don't need it as a parameter. Now I've explained recursion, this can modify this code
and have this as a return. Instead, I set up the
return value here. I define this up here. Let's remove that part. Let's store the results
in a results list here, because this will
be our return here. I no longer need to
pass this parameter in, and I no longer need
this as a parameter, but I need to define
a result in here. Let's do that now. Okay,
What I've done here, I've added a return
here to search, which is a list of a string. I've defined the result list of string inside
the method here. Now there's a couple
of things to note. The first thing I need to do is actually return this
out of the method. I'm going to do that. Now
the next thing I need to do, every time I recursively
call this same method here. I need to store the return every time I call it
recursively as well. Otherwise, we're going to
lose this information. If we're down in the very
depth of our folder structure, we've found some files, for example, like here. Well, we need to pass these out of the inner
call of the method, because for example, I'm
not storing a return here. What I need to do every time
I recursively call this, I need to store
the results here. Now you think, okay, it
looks like it's working. I've defined the list, every time I recursively
call itself, I'm remembering these
values and setting it here. Then every time we have a match, I'm adding it to the list, and I'm eventually returning it out and printing the results. Let's take a look and see what
happens. Let's say hello. It looks like we have
a bit of a problem. This is where debugging
is very useful, but I can tell you
what is going on here. The problem is we've
found some files in the inner depths of
our recursive calls, for example, these files here. Now this is two folders
deep, you can see here. Now what is happening is these
aren't being remembered, because when this
eventually comes out, we're resetting this value every single time we call
this recursive method. And that's a bit of a problem. We're adding the stuff here, but we're also resetting it. Nothing is being
remembered essentially, but we are actually adding
information in here. If I put a break
point type Hello, there are actually files here, but the problem is, it's
actually getting reset. If I look at my
Locals tab down here, I can monitor the
results right here. I set a break point on
return, hit a five. Now you can see I have one
result if I come out of here. Now you can see results
as reset to zero. As soon as I come out of here, nothing is being remembered. What is going on here. The problem is, well, it's quite a simple problem, but it's very hard to perhaps understand when
talking recursively, What we need to
actually do is add the results of this
search to this list. We can't just replace the list with the
results of the search, otherwise, we're
forgetting everything we've learned so far. What we need to do is add everything from the results
of the recursive search. And there's a method
called add range. And what that does, it adds one or more items to our list. And this is the
advantage of using a list over something
like a simple array. We have these methods
available to us. So let's take a look at this now and see if this
works any better. So I run the application, I type in hello, and now we have all
of our results. They're no longer getting raised through our recursive method. Calling this is why
having a return, it adds a little more
complexity into things. And that's why I introduced the example with a
parameter first. Because this isn't getting reset every single time when
we have a return, yes, we are defining the return here and initializing it
to a new area of memory. But we need to remember to add our results from
each recursive call, every time we call our
method recursively. Now, I appreciate
this is so much to take in, it's
super complicated. But I, I broke it down
in simple terms for you. If you watch this tutorial
maybe two or three times. And maybe provide your
own examples as well. You'll eventually figure it out and one day it
will just click. I promise you this is recursion in C Sharp.
Not only C Sharp. Recursion is in many
programming languages and even mathematics
and things like that. I hope you enjoyed this tutorial and thank you for watching.
79. 20-1. Final Project (Top Trumps Simulator Game): So the final project. What is the final project? Well, let's take a look. The final project is optional, but I highly recommend
you apply all of the knowledge that
you've learned so far and give it a solid attempt. Then you'll officially
earn the title, the unofficial title of C
Sharp Computer Programmer, or C Sharp Software Engineer. Sounds pretty good, doesn't it? So for the final project, we're going to be simulating
a top trumps game. Now if you're not
familiar with top trumps, it's basically a deck of cards. And the deck of cards is
themed for whatever you want, really whatever you want to buy. For example, you can
have a dragons with mystical creatures
where you have wizards and kings and dragons
and things like that. Each card has a character, this one's called
Dragon for example. And he has various stats
like strength skill, magic power on fear factor. However, if you buy a
deck with superheroes, they might have
something totally different with different
character names. But generally each deck
of cards is themed. When you create your
version of this in C sharp, you can choose whatever
theme you want. The Sky is the limit, Just use your imagination
how the game works. Well, I've included a
complete specification that explains how
the game works, but also some assumptions you can take when developing
this solution. I'm going to show
you a demo now, roughly on how it works. So here is the
specification right here, don't worry, I've included
this in text format, so do refer to it a few
times when sort of planning out your project and how you're going to
tackle the scenario. I give a brief description
of what it is. I've provided some links so you can do some
further research. Now, this is a two player game. We're going to be assuming there's only two
players playing. And I've put a list of
assumptions that you can make when creating this project
just to make it a lot easier. I don't really want you to
spend weeks and weeks on this. You can if you wish to,
it's no problem at all. But I think using
this specification, you know, a couple hours
a day for a week or so, I think that's a good amount
of time to sort of train your recent knowledge
and develop a nice piece of software
to show your friends, family, or whoever you want to refer to the specification on
how to get going with that. I'm going to show you my
solution now on how I tackled the problem so you can get an idea of how it works. So when the software
is first executed, we're just assuming
player one goes first. Player one can press Enter
to begin their turn. Now it's player one's turn. The player one has five cards and player two has five cards. So they have five cards each. So that the cards represent a character like a
dragon or a king, for example,
something like that. Here I have totally
random characters. That's, you know, how
good my imagination is. A randomly selected card or character from
my hand is played, and that is the teddy bear. Now, the teddy
bear has a height, a weight, magic power,
and a fear factor. Because it's a teddy,
it's quite small, it's not very heavy, It has no magic ability
and no fear factor. So it's actually
a very bad card. Now the idea is I want to
pick the highest stat here, and I hope that my opponent has a stat which
is less than mine. So if I pick height, say 1 meter 45. So I just choose the number
one here. I press Enter. Then the player,
the other player defends with Harry
Houdini, who's a magician. But he has a height of 5.7 So the teddy bear is not
taller than Harry Houdini. So the teddy bear loses because the teddy bear's
height is only 145. But Harry Houdini is
57. Player two wins. But because player to one, player two takes the
teddy bear card, player two retains their
Harry Houdini card. And now it's player
two turn to go. So if I hit Anton, Now you can see
player two now has six cards because they
won the teddy bear. Now it's player two's turn. The randomly selected
character is Picchu. Now Picchu has quite good
magic power, but quite short. And it's very light as well. And there's not
much fear factor. So I want to play magic power because it's quite high and I hope that I can beat the now
player one's defending card. So let's take a
look look at this. The other player defends
with Darth Veda. But I chose magic
power, which was 75. However, Darth Veda only has a magic power of two. So I won. I won again. Now
because I won again, it's still my turn. So it's still player two's turn. Now you can see I
have seven cards. The winner of the game is the person who has all ten
cards in this example, because there's only ten cards. If you create 20 cards, then obviously the winner
is with all 20 cards. Now, there's a lot
of assumptions here. You can see I'm
randomly selecting characters from the deck which the player
each player has. Whereas when you actually
play this game in person, you take the one on
top of the deck. So, I'm using a lot of
assumptions just to shorten the sort of
lifespan of this project. You know, I don't, I don't
really want you working on this for 34 months and
pulling your hair out. I don't think that
will be a very fun first and final
project for you. So there are a lot
of assumptions, you know, it's not
really mandatory. Add your own twist.
Add your own flavor. It's really up to
you, obviously, I've just played Picature, and Piccature has
been selected again. So you know, it's not
a perfect application, so don't worry about
it being perfect. It's just to train your
knowledge and things like that. So it's just a bit
of fun and I think you'll have quite a good
time with this here. We've got the mini devil, We're fear factor four. We're doing pretty well.
We have nine cards now we have Harry
Houdini magic power. And it looks like
we've won the game. Player two got all ten cards totally destroyed, player one. Do we want to play
again? Yes or no? If I press no, then
thank you for playing. Press Enter to exit. That is the final project. Again, it's not the solution, It's just a solution. You can do whatever you want with whatever
characters you wish, but try to apply a lot of the things we've actually
covered in the course. So here I've created, on the right hand side here, I've created four
custom classes. Here, I've put them in
a separate project. And when I open the main method right here in the program class, you can see there's not
really much code in here. That's because we've
separated it off into, you know, logical containers. I have a game
controller class that manages everything
to do with the game, the turns, and
everything like that. I have a player class now, the players, it
models the players. And a player holds a number
of characters or cards. And the character
or card class is responsible for all the
characters in the game. So you can see how we're using the knowledge
we've applied. Where we take a class
and that class is responsible for everything
to do with what it's called. So the character class
deals with characters, the game controller
deals with how the game works, et cetera. So that's really how it works. We're taking all
the knowledge we've taken and we're applying it now. So that is basically my solution towards the final project. You know, Planet Planet. Use some notepads.
Use some paper. Use a pen. Have a good think about how you're going
to tackle the problem, how you're going to
organize the problem, and what techniques
you're going to use, what loops, conditions,
and things like that. I hope you have fun with this. The final project tests
your knowledge on many concepts of the things
we've covered so far. So classes, objects,
instantiation, if statements,
switch statements, conditions Boolean and
logical operators. Four loops, wire loops, lots of different loops, methods and much more. So it's a great way to
take all of that knowledge and apply it to one
piece of software. How long will the
final project take? Well, if you enjoy programming and you want to be a programmer, then this should not
be a concern at all, because practice is
always a good thing. If you're a total beginner
when you started this course, then perhaps spend a
couple of hours each day for a week or so,
something like that. Like any other language,
French, German, Spanish. You're not going to absorb all the information
in one run through. It's just not realistic. But use the course materials as a reference point for
the final project. If you're developing
your final project and you can't remember
how to do a wire loop, for example, then just rewatch the wire loop tutorial again
just to get a refresher. Even professional
computer programmers use Google and various other
websites as a reference point, and sometimes they do this. Daily programming is
all about thinking outside of the box and applying lateral and
logical thinking. It is not about remembering syntax and regurgitating syntax, so don't be deterred
by this at all. So I've included my solution
for the final project, but I highly recommend
you just do not use this. Do not look at it until
you've finished yours. Then you can use it
as a reference point to perhaps, maybe improve yours. Or look at the differences between my solution
and your solution. Remember, there's not one
solution to a problem. There can be multiple solutions and all of them being correct. But use it just as
a reference point when you've completed
your final project. Send it to your friends.
Send it to your family. Upload it to Youtube for
example. And send me the link. I would love to see your
final projects and how you interpreted this
specification and put your own twist on it. The last thing I want to say is, good luck with the
final project and good luck for your future
programming endeavors. Finally, thank you. Thank you very much for
watching Take care.
80. 20-2. Course Summary (Where do I go from here?): Now, all good things
must come to an end. But if you've made it this far, then thank you for watching. If you have any queries,
problems, niggles, questions regarding any of the content in the
entire course, then please leave a message on the content itself or
send me a message. I'll be more than happy
to help also review the accompanying project
files if you haven't already. Most lessons in this
course have accompanying project files and feel
free to expand on them, learn from them, but also
add your own twist to them. The limit is your imagination. The big question many people typically have after
finishing a course is, where do I go from here? Well, I'm not going
to leave you hanging. A lot of people do, but I'm
going to give you some ideas. It does depend what
your goals are. What are your goals? These are unique to you, They're
personal to you. For example, maybe you're
looking for employment. You want to get employed by somebody. Or maybe it's a hobby. Maybe you want to create a phone application
to make money. Or maybe you want to
make video games in Unity or just to try
a new challenge. Something totally new.
So it does depend. But the secret and common
ground with all of these is practice,
practice, practice. C sharp is not too
dissimilar from a real spoken language like French or German or
Portuguese for example. The more you use it, the better you will become. It's only natural.
And similarly, the less you use it, the more you will forget. So in your free time,
I recommend creating small software
applications to solve your everyday problems and
make your life easier. Not only that, it's
quite fun as well. I've made lots of different pieces of software
just to make my life easier. For example, I've made a music renamer when I
have itunes, for example. Sometimes it doesn't
take the file name, it takes a hidden tag inside
the MP three, for example. So I made a piece of software
to inject that tag into the MP three so that my itunes looks really nice
and it's all automated. I don't have to, you know, rename every single song to give it the correct
artist or title. For example, this is
very easy to do with a lot of the tools
and techniques we've covered in this course. Things like when free items come up on Craigslist
or things like that, I can play a music sound. So anytime somebody is giving
something away for free, my laptop starts playing music. And then I know something
new is in the free section and I can instantly
contact the buyer and, you know, arrange
collection of that. You know, the limit
is your imagination. And lastly, I've created
a Youtube bulk uploader. What happens is, if you have
maybe ten or 50 videos, you want to upload to Youtube, but you don't want to type out all the titles and descriptions
and things like that. So I've made an application
where I can take 50 videos, for example, drag and drop
them onto the software. And it populates the video
title and description and even the tags from the
name of the video file. And this saves so many hours. And this is actually a commercial
piece of software now. So not only does it practice
my programming skills, but it also earns
money on the side. So there's a lot of ideas
there you can, you know, take on board and apply for
your own specific scenarios. Another thing you can do,
which is really, really good, is take online coding tests, like little coding challenges. So for example, there's
two websites you can use. One is called Hacker Rank and another one is
called Lite Code. I'll show you those now. Now each one of them has lots of different coding challenges, just like I presented the final project with
the top trump simulator. But typically,
they're a lot easier. For example, draw a pyramid, which we've covered
in this course, or draw a square or find the
queen, things like that. So quick challenges that
test your lateral thinking, which is thinking
outside of the box. So not only do they test your
knowledge of C Sharp and perhaps your memory of the
syntax, but more importantly, your application of a Sharp When you're presented
with a problem, it tests how your brain works, how you understand the
problem and find a solution. Usually these challenges are very unique and very specific. You can't really Google them and find a solution, for example. So if you practice these
coding challenges a lot and home your
ability on solving them, improving your lateral thinking, then this will make you very attractive to
potential employers. Employers do not
look for people who can regurgitate and
remember syntax. They look for people and they
encourage lateral thinking. And these online coding
tests are perfect for that. Not only that, these two
websites that I've suggested, they track which exercises
you've already solved. And they create a profile
like a little leader board. You know which ones
you've solved. And I don't see any
problem in printing this off or sending it
to a potential employer. Then they can actually see
what challenges you've done. And they can see that, you know, it's not just a career you might want or a job you actually
enjoy doing this. And this is what
they look for and this is what separates
you from other people. And again, it's not only
all about getting a job. Even hobbyist people love
these coding challenges. You know, it really
works your brain. It's a really good training
exercise for your mind, so I highly recommend
online coding tests. One more thing you can do is practice sample job
interview questions, even if you're not planning
on becoming employed. Because they really test your
knowledge and put you on the spot when you remove this
course from your laptop, for example, say you cover it with your hand or a book and actually ask yourself,
what is polymorphism? Can you answer that
question without looking at this course or googling it for
example? Is that possible? What if I asked you, what is method
overloading or what do I mean when I say abstract
or abstract class? And what is encapsulation and how does that differ from,
you know, another term? Can you honestly answer
these questions? So this is how you
really test yourself, whether you understand
the principles. It's easy to watch someone else talk about
something and say, oh, okay, yeah, I understand it. But if you cover the material with your hand and hide
it from your view, can you honestly say, okay, polymorphism is this. So it's one thing, reading something and
understanding it, but it's another thing, reciting it back in your own words. And that is very important
not just for getting a job, but also really understanding everything covered
in this course. So I do highly recommend
doing this as well. So the last thing
I'm going to mention in terms of what
shall I do next, why you took this course. Some people may have taken this course to move
onto something else. Perhaps you wanted to do
game development in Unity. Maybe you wanted to
develop websites, so you needed to know the sharp. Then you may learn the
Spot Net, for example. Or maybe you want
to create forms for a desktop application or
a mobile application. You can apply sharp to
all of these scenarios, but they require more
knowledge in order to successfully fulfill the role or fulfill what you want to do. But in terms of knowing and understanding and
practice in C sharp, this course will be very
useful for those applications. I can tell you that 100% if you want to start
creating games in Unity, you will find that you'll know pretty much
all the C sharp. You need to know, or at
least know how to look and research for any new methods
and classes you wish to use. Any required knowledge to
create video games in Unity will evolve around understanding and learning the Unity engine, for example, which
is very different. But in terms of C Sharp, you're covered again for
creating mobile applications. The C sharp already covered, Perhaps you just need to learn a few graphical or niche things to do with mobile applications. So again, this se
shop course will be a perfect foothold for
whatever you want to achieve. Whatever your end goal might be. So the last thing
I'm going to say is, again, thank you very
much for watching. Do not forget to share your final projects with me if you wish to undertake those. If you have any questions, send me a message
and leave a comment. And just let me know how
the course was for you. And perhaps in five
to ten years time when you're a professional
software developer, maybe you can send me a message and just let me know
how you're getting on and tell me whether this course helped
you in the long run. I will be creating more courses, so feel free to check those
out for the final time. Thank you very much for
watching Take care.