IntroductionWelcome| 00:04 | Hi! I am Joe Marini, and I'd like to
welcome you to C# Essential Training.
| | 00:08 | I've been working with C# since
its initial release back in 2001.
| | 00:12 | C# is a great choice for
applications that run on a wide variety of
| | 00:17 | Microsoft platforms.
| | 00:18 | We will start off with the basics:
| | 00:20 | installing the free C# development tools
from Microsoft, understanding the basic
| | 00:25 | structure of a C# program,
and getting your first program up and running.
| | 00:30 | Then we'll move on to more advanced
concepts, like defining your own C# classes.
| | 00:35 | I will also cover subjects like
automatic memory management and reading and
| | 00:39 | writing data files, and we'll see how
to do all of this while using the free
| | 00:44 | Visual C# Express development tools to
build and debug your C# applications.
| | 00:50 | So if you're ready to take a look at
the foundation language for targeting
| | 00:53 | Microsoft platforms then let's get
started with C# Essential Training.
| | Collapse this transcript |
| What you should know| 00:00 | In this course, I am going to
make a couple of assumptions.
| | 00:03 | First, I am going to assume you
have some experience working with
| | 00:06 | Windows-based computers.
| | 00:08 | Second, I'm going to assume that you
have some amount of prior programming
| | 00:12 | experience--not necessarily a lot of
experience, and I don't expect that you've
| | 00:16 | ever even seen C# before.
| | 00:19 | But you do need to at least know
what things like variables, functions,
| | 00:23 | loops, et cetera, are.
| | 00:24 | These are the basic fundamentals of
any programming language, not just C#.
| | 00:29 | Just to be clear, this course is not an
introduction to the fundamentals of programming.
| | 00:33 | What we are going to be focusing on are
the fundamentals of the C# language itself.
| | 00:39 | Along the way, we will do some
work with the .NET framework, which is
| | 00:42 | Microsoft's runtime and class library
that C# uses to build and run programs,
| | 00:47 | but we will mainly focus
on learning the C# language.
| | 00:51 | If you already know a programming
language, like C or Java or Objective-C or
| | 00:57 | JavaScript, then many of the C#
constructs will look very familiar to you,
| | 01:02 | but don't be fooled;
| | 01:02 | C# is its own language with its own way
of doing some things some of which are
| | 01:07 | different from all the
other languages out there.
| | 01:10 | Of course, if you're coming from a very
different language, like Ruby or Python
| | 01:15 | or Perl, that's fine too;
| | 01:17 | you won't have any problem
following along with this course.
| | Collapse this transcript |
| Using the exercise files| 00:00 | If you are a Premium member of the
lynda.com Online Training Library, or if
| | 00:04 | you're watching this tutorial on a
DVD-ROM, you have access to the exercise
| | 00:09 | files used throughout this title.
| | 00:11 | If you look inside the exercise files,
you'll find folders that contain all the
| | 00:16 | various exercises that I'm
going to use in this title.
| | 00:19 | The way that they're organized is, each one of
the chapters has its own set of example files.
| | 00:24 | So for example, if I look inside the
folder for Chapter 5, you will notice that
| | 00:28 | there are bunch of subfolders that are
named according to the particular section
| | 00:32 | that's being described in
that particular chapter.
| | 00:35 | If you look inside these folders,
you will notice that there is a C# Express
| | 00:40 | project file, along with a folder that
contains the code for that exercise.
| | 00:45 | When you have installed the Visual C#
Express developer tools from Microsoft,
| | 00:50 | you'll be able to just simply double-
click on the name of the project file,
| | 00:54 | which will then bring up the coding
environment and the code that's in that file,
| | 00:59 | and you can start working right away on it.
| | 01:01 | Let me take a look back in the Exercise
Files folder. You'll also notice that
| | 01:06 | there is a FinishedExamples folder.
| | 01:09 | In this folder, you will see the same
folder structure, but what I've done here
| | 01:13 | is finished off each one of
these examples in the finished state.
| | 01:17 | So here in the upper part of the folder,
these are all the examples in the start state.
| | 01:22 | These are so that you can follow
along with me as you take the course.
| | 01:25 | If you would rather just jump ahead
and see how a finished example works, you
| | 01:28 | can go inside the FinishedExamples
files folder and then just choose which
| | 01:32 | chapter you want to the finished example
for and then go ahead and examine that code.
| | 01:36 | The last thing I want to point out
is that I have included a file here
| | 01:39 | called ExampleSnippets.
| | 01:41 | If we open this text file up, you will
notice that this is just a collection of
| | 01:45 | code snippets that I'm going to use in
each one of these examples throughout the
| | 01:49 | title, and I have organized
them in various chapters.
| | 01:52 | Here are the snippets for Chapter 3,
| | 01:54 | here are the snippets for Chapter 4, and so on.
| | 01:57 | This is so you don't have to sit
and watch me type each example out.
| | 02:01 | I'm going to just simply copy and paste
the code that's in these snippets files.
| | 02:05 | Now if you're a Monthly member or
Annual number of lynda.com, you don't have
| | 02:10 | access to the exercise files, but you
will have access to this ExampleSnippets
| | 02:13 | file because it will be made
available as a free download.
| | 02:16 | So you can either follow along from scratch
with your own assets, or you can use the snippets.
| | 02:21 | Let's go ahead and get started.
| | Collapse this transcript |
|
|
1. Getting Started with C#Installing the Visual C# Express IDE| 00:00 | Okay, so we are ready to start writing
our C# code, but before we can do that,
| | 00:03 | we have to go get our development environment.
| | 00:05 | So to do that, we are going to go to
the Microsoft web site and download the C#
| | 00:10 | Express development environment.
So let's do that and go to the browser.
| | 00:13 | In the browser, I am going to
type in microsoft.com/express.
| | 00:19 | This will take me to the download
page for the various versions of Express
| | 00:25 | products that Microsoft
makes available for free.
| | 00:27 | And this page might look a little bit
different for you when you get here, but
| | 00:31 | there should be a link to download the
Express products for Visual Studio, and
| | 00:36 | that's this link right here that says,
"Get free Visual Studio Express products."
| | 00:39 | So I am going to click on that.
| | 00:40 | This will take me to a download page for
all of the Visual Studio Express products.
| | 00:46 | And as I scroll down the list, you can
see that there's one for Windows Phone.
| | 00:49 | There's Visual Web Developer. And I am
just going to scroll down until I get to
| | 00:52 | this link right here,
and that is Visual C# 2010 Express.
| | 00:57 | And again, when you get here, this may
be newer. The point, though, is that
| | 01:00 | you want to get the most recent
version of the Visual C# Express IDE.
| | 01:04 | So I am going to click on that link.
| | 01:06 | This will take me to the download page for
that particular version of Visual C# Express.
| | 01:11 | So I can click on the Install Now link.
| | 01:14 | Now depending on what browser you're
using, you're going to be prompted to
| | 01:17 | download and run the installer,
and you can see here in IE I have got this
| | 01:21 | little download bar, but this is going
to look different for you if you're using
| | 01:24 | a different browser.
| | 01:25 | Now I have already done this.
| | 01:27 | So once you have run the installer and
Visual C# Express is installed, you will
| | 01:32 | find it in your Programs menu.
| | 01:34 | So if I go to the Start menu, you will
see I have got Microsoft Visual C# 2010
| | 01:39 | Express, or something like it for you.
And I am going to go ahead and click on the
| | 01:42 | link to make sure it's installed
correctly. And you can see that Visual C#
| | 01:46 | Express fires up, and it
looks like we are ready to go.
| | 01:48 | Now there is one other thing I wan to
show you before we actually get started
| | 01:51 | writing some code, and that is the
Microsoft Developer Network Library.
| | 01:54 | So let's jump back to the
browser and head over there.
| | 01:57 | So back here in the browser, I am
going to make a new tab, and I am going to
| | 02:00 | type msdn.microsoft.com.
| | 02:04 | This is the online library for the
Microsoft Developer Network, and it contains
| | 02:09 | all the documentation that you'll
need to build your C# and .NET programs.
| | 02:15 | And you can see when I come here it's
placed me on one of these four categories.
| | 02:18 | In this case it's Tasks.
| | 02:20 | Let me click on the Platforms link.
| | 02:21 | And under Platforms, you can see that
there are categories for desktop and web
| | 02:26 | and cloud and phone. And if we scroll
down a little bit, there is a whole bunch
| | 02:30 | of content on here that's focused on
building applications for the various
| | 02:34 | Microsoft platforms.
| | 02:35 | Let's scroll back up.
| | 02:36 | I am going to click on Tasks again.
| | 02:39 | You can see it takes me to a different
pivot on the information here in the MSDN Library.
| | 02:44 | There is a section for creating code.
| | 02:46 | There is a section for testing.
| | 02:47 | There is a section for understanding code.
| | 02:49 | Let's go ahead and click on one of
these links for understanding code.
| | 02:51 | You can see here, as I scroll down,
there is a whole bunch of overview material
| | 02:55 | for understanding how to build .NET
applications using a variety of languages.
| | 03:00 | We are going to be referring back to
the MSDN Library throughout the course to
| | 03:04 | see documentation for the various
kinds of code and objects we will be using.
| | 03:08 | In fact, if I click on the Library
link up here, the Library link takes me
| | 03:12 | directly to the documentation for the
various parts of C# and .NET. And you
| | 03:18 | can see over here under the MSDN Library
section, there is links for all kinds of categories:
| | 03:23 | Development tools and Languages,
.NET Development, and so on.
| | 03:26 | This is the web site that we will be
referring to for Microsoft's canonical
| | 03:30 | documentation for various parts of C#.
| | 03:33 | Okay, so now that we have got the IDE
installed and we know MSDN is, we are
| | 03:37 | ready to start building
our first C# application.
| | Collapse this transcript |
| Creating your first C# application| 00:00 | Now that we have got the IDE
installed and we've seen MSDN,
| | 00:04 | let's go ahead and fire up C#
Express and build our first application.
| | 00:09 | So I am going to go ahead and launch
C# Express. And when C# Express comes up,
| | 00:17 | you will see a start page and
the application window frame.
| | 00:22 | So this right here is the start page.
Over here is something called the Solution
| | 00:25 | Explorer, and we will look
at that a little bit later.
| | 00:27 | What I am going to do, just really quickly, is
get our feet wet by writing a C# application.
| | 00:33 | I don't expect that you're going to
understand everything that I'm going to show you right
| | 00:35 | away, but I know you're
probably anxious to get started.
| | 00:38 | So let's just go ahead and build a
simple application. And once we've done that,
| | 00:41 | we'll take a quick look at how we did it,
and then we will have an introduction
| | 00:45 | to C# Express that explains the
various parts of the program that we will be
| | 00:48 | using throughout the course
to build our applications.
| | 00:52 | I am going to go ahead and click on the
New Project link right here. And when I
| | 00:56 | click on the New Project link, you'll
notice that a dialog comes up asking me,
| | 00:59 | well, what kind of
application do you want to build?
| | 01:01 | You can see there is a whole bunch of
built-in ones that we can choose from:
| | 01:05 | there is Windows Forms Applications,
there is WPF, there is something called a
| | 01:09 | Console Application, there's Class
Library, and there is a whole bunch of other
| | 01:12 | things that we can choose from.
| | 01:14 | To keep things simple, we are going to
build what's called a console application
| | 01:17 | and you may have heard this referred to
in the past as something like a command-
| | 01:22 | line app, or something like that.
| | 01:24 | The point here is that we are not
going to be focusing too much on fancy user
| | 01:28 | interface or anything like that.
| | 01:29 | We are going to build console
applications to keep us focused on the C# language.
| | 01:34 | I could name it down here something
else, but this is just an example.
| | 01:37 | So let's go and click on Console
Application, and you can see that C# Express has
| | 01:43 | created a sample application for me.
| | 01:46 | It's opened up a file here called
Program.cs--that's this tab right over here.
| | 01:51 | If we take a look now at the Solution
Explorer, we can see the Solution Explorer
| | 01:54 | has now been filled out with a bunch of things:
| | 01:57 | There is the name of the
application that we are building right here.
| | 01:59 | There is a couple of folders called
Properties and References, and we will see
| | 02:02 | those in depth a little bit later.
| | 02:04 | And then this file right here called Program.cs.
| | 02:07 | Program.cs is the C# file that contains
the code for our program, and it happens
| | 02:12 | to be opened in the window right here.
| | 02:14 | I am going to go ahead and just type
a couple of things, and again, I don't
| | 02:18 | expect you to know this right away,
but just follow along with me.
| | 02:22 | Inside the function for Main, I
am going to type Console.WriteLine.
| | 02:31 | It's a bit of a tradition in
programming courses that the first application you
| | 02:36 | write basically does nothing more than
print "Hello World" out to whatever output
| | 02:40 | device you're using,
| | 02:41 | so I am going to type in here
"Hello World," and I am going to save it.
| | 02:49 | Now what I am going to do is run it,
and I can run it a couple of different ways.
| | 02:53 | What I am going to do is
go up to the Debug menu.
| | 02:56 | You can see that I have got an option
here for Start Debugging and I have got
| | 03:00 | something called Build Solution.
| | 03:01 | I will just quickly choose Build
Solution to make sure that everything is right,
| | 03:06 | and you can see down here in the
status bar there is a little piece of text
| | 03:08 | that says, "Build succeeded."
| | 03:10 | So everything looks okay.
| | 03:12 | Now I am going to run it.
| | 03:13 | And instead of going back to the Debug
menu, I am going to click on this little
| | 03:16 | green arrow right here
that says Start Debugging.
| | 03:18 | So I am going to click on that and you
can see that some window came up very
| | 03:22 | quickly and went away, and that's
because the Console Application came up, the
| | 03:28 | text was written out, and then the program ended.
| | 03:30 | The .NET Library said, "Oh, I guess we
don't need the console window anymore.
| | 03:33 | Might as well send it away."
| | 03:34 | So to keep that from happening, I am
going to add one more piece of code down
| | 03:38 | here, Console.ReadLine,
and now I am going to save that.
| | 03:45 | Now this is going to have the console
window wait for us to give it a line of text.
| | 03:49 | This is just a way for me to keep the
console window from going away as I show
| | 03:54 | how this program works.
| | 03:55 | So let's try it one more time.
| | 03:56 | Let's go ahead and click on Run. All right!
| | 03:59 | You can see that the console window
comes up, the words "Hello World" got printed
| | 04:03 | out, and now it's waiting for me to give
it a line of input, and it's going to sit
| | 04:07 | there until I do that.
| | 04:08 | You can see in the background the UI
for C# Express has changed somewhat.
| | 04:14 | The Program.cs window has been
expanded, and we've got these two other windows
| | 04:18 | down here called Locals and Call Stack--
and we'll get into this later on when
| | 04:22 | we look at debugging.
| | 04:23 | This is C#'s way of showing me what
the program is doing while it's running.
| | 04:27 | So let's bring this back up here,
and you can see now that when I give it a line
| | 04:31 | of text and the ReadLine function
completes, the Console window goes away and C#
| | 04:36 | Express goes back to the
state where it first launched.
| | 04:40 | That's how we build our first C#
program and to get further into the course, we
| | 04:44 | will explain how all of these things work.
| | Collapse this transcript |
| Introduction to Visual C# Express| 00:00 | Since we're going to be spending a lot
of time using C# Express to build our
| | 00:03 | applications, we should probably take
a few moments and get familiar with the
| | 00:06 | IDE and see how it works.
| | 00:08 | So I'm going to go ahead and
launch the C# 2010 Express,
| | 00:14 | and you'll see that when the
application comes up, it's a very simple UI.
| | 00:17 | There's the start page right
here on the left-hand side,
| | 00:20 | and then over here there's
something called the Solution Explorer.
| | 00:24 | A couple things you need to
know about C# right upfront.
| | 00:26 | C# Express organizes everything into projects.
| | 00:31 | Projects are what applications are made from.
| | 00:33 | And you might sometimes hear the word
project interspersed or interchanged
| | 00:37 | with the word solution.
| | 00:39 | That's not completely true.
| | 00:40 | Solutions are basically top-level
projects that can contain other projects.
| | 00:45 | When we build a project, it will
appear in the Solution Explorer here on the
| | 00:49 | right-hand side of the screen.
| | 00:51 | So let's go ahead and create a new project,
| | 00:54 | and we can do that one of two ways:
| | 00:55 | we can click on the New Project link
here in start page, or we can go up to the
| | 01:01 | File menu and choose New Project.
| | 01:03 | So I'm going to choose New Project,
| | 01:06 | and the New Project dialog launches and we can
choose what kind of project we want to build.
| | 01:11 | Throughout this course we'll be
working with console applications, because
| | 01:15 | it gets the user interface out of the way
and just let's us concentrate on the language.
| | 01:19 | So I'm going to go ahead and click on
the Console Application to select it.
| | 01:23 | If it's not already done so,
you should do the same thing.
| | 01:25 | Down here in the bottom of the dialog,
there is a place where we can enter the
| | 01:29 | name of the project.
| | 01:31 | And I'll just type in something;
| | 01:32 | I'll just call it MyProject.
| | 01:34 | And I'm going to click the OK button.
| | 01:37 | This is going to create the
project for us. All right!
| | 01:41 | Now that we have the project built,
let's take a look at C# Express and see
| | 01:46 | what's going on here in the UI.
| | 01:48 | So over here in the Solution Explorer
you'll notice that the window has been
| | 01:52 | filled out with some information, and we
will get back to that in just a moment.
| | 01:56 | The project code is over
here opened in the editor.
| | 02:00 | And the new project isn't actually saved yet.
| | 02:02 | It is fully functional.
You can go ahead and run it. You can edit it.
| | 02:05 | You can do all kinds of things.
| | 02:06 | But it's sitting out in
temporary space right now.
| | 02:09 | If we wanted to actually put all this
work onto disk, we would go the File menu
| | 02:13 | and we would choose Save MyProject or Save All.
| | 02:17 | And when I choose Save All, you'll see that I
get a dialog that says hey, here's the name.
| | 02:21 | Here's where it's going to be saved.
| | 02:22 | Here's what the solution name is.
| | 02:24 | I have the option to create
a directory for the solution.
| | 02:26 | And at this point I can choose to name
it something else if I don't like the
| | 02:30 | name that I originally came up with.
| | 02:32 | And I'm just going to go ahead and choose Save.
| | 02:35 | That will put the project on disk for
me in the Documents folder, or whatever
| | 02:39 | path I selected in the Save dialog.
| | 02:42 | Let's go ahead and take a look at the
project files over here in the Solution Explorer.
| | 02:46 | You'll see that underneath the top-level
MyProject heading there are a couple of folders.
| | 02:51 | There's the Properties folder and References.
| | 02:53 | Let's go ahead and expand those.
| | 02:56 | Underneath Properties there's
a file called AssemblyInfo.cs.
| | 03:00 | Now I'm just going to quickly open
this up so you can see what's inside it.
| | 03:02 | We won't be going through this in
this course, because this is a little bit of
| | 03:05 | advanced information.
| | 03:06 | But this is the information that
C# Express will save, along with your
| | 03:10 | application, that describes to the .NET
Framework what the application is, how
| | 03:14 | it works, various pieces of
information that .NET needs to know about the
| | 03:18 | program in order to run it.
| | 03:20 | So let me go ahead and close that.
| | 03:22 | Under the References folder you'll see
a whole bunch of things, like Microsoft
| | 03:25 | and System and so on.
| | 03:27 | These are the actual .NET Framework
libraries that get associated with your
| | 03:31 | project when you make a new one.
| | 03:33 | These will change based upon what
kind of project you're creating.
| | 03:37 | In this case, we've built a console
application, so these are the .NET libraries
| | 03:41 | that the console application needs to run.
| | 03:44 | Some of them are optional; some of them are not.
| | 03:46 | The .NET Framework just goes ahead and
includes them in case you need to use them later.
| | 03:51 | So let's go ahead and close those folders up.
| | 03:53 | The Program.cs file,
| | 03:55 | this is the default file that gets
created, along with your application, that
| | 03:59 | contains your main code for the application.
| | 04:02 | And you can choose to add new C# files
as you go along, depending on how complex
| | 04:06 | your application is.
| | 04:07 | We're not going to do that right now.
| | 04:09 | Let's just take a trip through the user
interface of C# Express, so we can see how it works.
| | 04:14 | I've already shown you the File menu.
| | 04:16 | That's up over here.
| | 04:17 | This is where we create
projects and save things.
| | 04:19 | Pretty standard file-menu stuff.
| | 04:21 | Let's move over to the View menu.
| | 04:23 | In the View menu, you'll see it's pretty simple.
| | 04:25 | I can choose to view the start page again.
| | 04:27 | There's other windows that we'll be looking at.
| | 04:29 | I'll just go ahead and choose one right now.
| | 04:31 | This one is the Error List.
| | 04:32 | This window down here shows you if
there are any errors or warnings or
| | 04:36 | anything else in your code.
| | 04:37 | And we'll get back to that later,
so let's go ahead and close that.
| | 04:40 | Also under the menu, there are
toolbars, and you can see that I've got
| | 04:43 | some toolbars showing.
| | 04:45 | The Project menu is where we
control what's in our project.
| | 04:48 | So we can add items to the project,
we can add references, and so on.
| | 04:52 | We're not going to do that right now,
but we'll probably do it later.
| | 04:54 | Under the Debug menu, this is how we run
the application in order to test it out.
| | 04:59 | We can also build our solution right here.
| | 05:02 | This will build the program
without actually running it.
| | 05:04 | I'm going to skip over the
Data menu and go to Tools.
| | 05:08 | Under the Tools menu, I'm going
to show you a couple of things.
| | 05:10 | First, under Settings, there's a
couple of ways that you can use C# Express.
| | 05:14 | There's Basic Settings
and there's Expert Settings.
| | 05:17 | I've left it on Basic Settings right
now because we are not going to be using
| | 05:20 | any of the Expert Settings
for now in our application.
| | 05:23 | What I'm going to do, though,
is show you under Options.
| | 05:25 | Now under the Options dialog, there
are a couple things I've changed that
| | 05:29 | you might want to change along with me
to make some of the examples a little
| | 05:32 | bit easy to follow.
| | 05:33 | You can see that under Fonts and Colors
I've changed the Size and the Font to
| | 05:37 | make things readable.
| | 05:38 | Now there's a check box down
here that says Show all settings.
| | 05:42 | So I'm going to check that for a moment.
| | 05:44 | You can see that when I do that, a
whole bunch of other settings show up.
| | 05:46 | What I'm going to do is, under
Text Editor, I'm going to choose C#.
| | 05:51 | And you can see that there's an
option under Display for Line numbers.
| | 05:54 | Now that's not there if I turn
off the Show all settings function.
| | 05:58 | So turn on Show all settings and then
go down to the C# option here and check
| | 06:04 | the Line numbers option to show
line numbers in your code. Click OK.
| | 06:09 | And that pretty much completes our
tour through the UI for using C# Express.
| | 06:14 | We'll see more of this as
we go throughout the course,
| | 06:17 | but for now that should be a nice
overview introduction to the application
| | 06:20 | and how it works.
| | Collapse this transcript |
|
|
2. C# Language FundamentalsOverview of the C# language| 00:00 | C# is a language that was built by
Microsoft for working with Microsoft's .NET
| | 00:06 | application platforms.
| | 00:08 | It is a language that's very similar to
other languages you may have seen, such
| | 00:12 | as JavaScript or Java or C, C++, Objective-C.
| | 00:17 | If you've used any of these languages in
the past, you're going to feel right at
| | 00:21 | home pretty much in C#.
| | 00:23 | Syntactically, the language is very similar.
| | 00:26 | C# is what's called a managed-code environment.
| | 00:29 | Memory management is automatic.
| | 00:32 | So if you've worked with other
languages, like C or Objective-C, then you've
| | 00:37 | probably come across situations where you
have to create and destroy objects on your own.
| | 00:43 | C# does all of that for you.
| | 00:45 | When you create an object, the C#
interpreter, or compiler, actually takes care of
| | 00:50 | making sure that that memory is
returned to the system at some point, and you
| | 00:54 | don't have to worry about it.
| | 00:55 | C# is a compiled language.
| | 00:58 | Unlike some other languages you may be
familiar with, like JavaScript or Perl,
| | 01:01 | you must first build a C#
program before you can run it,
| | 01:05 | and this step is called
compiling the application.
| | 01:09 | JavaScript and Perl are interpretive languages.
| | 01:12 | In other words, the execution engine--
in the case of JavaScript, for example,
| | 01:16 | that would be the browser--actually
interprets the language line by line, as it
| | 01:20 | goes through the program and runs it
as it discovers new statements and other
| | 01:25 | things in the language.
| | 01:26 | C# isn't like that.
| | 01:27 | In C#, you write your code, then you
have to go through the compilation step,
| | 01:31 | and then you can run the application.
| | 01:34 | Now at its heart, C# is an
object-oriented programming language.
| | 01:38 | In C# pretty much almost
everything can be treated as an object.
| | 01:42 | I've underlined the word "almost" there,
because there are a couple of esoteric
| | 01:46 | cases where not everything is an object.
| | 01:48 | But for our purposes in this course,
you can pretty much think that everything
| | 01:52 | in C# is an object and can be treated that way.
| | 01:56 | In fact, in C# there are no
global functions or variables;
| | 01:59 | everything is in classes.
| | 02:01 | And that might be different from other
languages you might be familiar with, like
| | 02:04 | JavaScript or like C. But in C#
everything has to be inside of a class, and
| | 02:09 | we'll come across that as we
go further into the language.
| | 02:12 | Now as I mentioned earlier, C# is a
foundation for working with many different
| | 02:17 | Microsoft platform technologies.
| | 02:20 | At the bottom of the stack is
something called the Common Language Runtime.
| | 02:24 | This is the execution engine, or virtual
machine, or whatever you want to call it,
| | 02:28 | that actually interprets all the
various bytes that the program gets compiled
| | 02:33 | down to and is what runs your code.
| | 02:36 | On top of that are the
Microsoft .NET Framework Libraries.
| | 02:40 | This is the code that is provided to
you by .NET that performs a whole bunch of
| | 02:45 | common things that applications have
to do, such as reading and writing from
| | 02:48 | files, working with the web,
and all that kind of stuff.
| | 02:51 | That's all contained in
the .NET Framework Libraries.
| | 02:55 | On top of that is the C# language,
which we will be working with today.
| | 02:59 | But the thing about .NET is that it was
designed to work with lots of languages.
| | 03:03 | There are other languages like VB.NET,
such as Visual Basic, or Python, and so on.
| | 03:08 | But we're not going to concentrate on those;
| | 03:09 | we're going to be using C#
throughout this course.
| | 03:12 | What this allows you to do is
use one language to target many
| | 03:16 | different platforms.
| | 03:17 | So using C# and .NET, you can build
applications that will run on Windows,
| | 03:22 | Windows Phone, Silverlight, SharePoint,
ASP.NET, Xbox, and a whole bunch of others.
| | 03:29 | So just by learning this one language,
you can build applications that run in
| | 03:32 | many, many different places.
| | 03:34 | C# got its start way back in 2001.
| | 03:38 | This was when Microsoft released the
first version of .NET--that was .NET 1.0.
| | 03:43 | That was where C# burst on to the
scene, and it continued along for a couple
| | 03:48 | of happy years, until 2003 came along, which
was when Microsoft released .NET version 1.1,
| | 03:54 | and that was when C# 1.2 was released.
| | 03:57 | Not a whole lot of different changes
between the initial C# release and 1.2--
| | 04:01 | a couple of cleaning up
things they did in the language.
| | 04:03 | But 2005 was when things
began to get interesting.
| | 04:06 | That was when .NET 2.0 came out.
| | 04:08 | And .NET 2.0 introduced some
neat little things into C#,
| | 04:13 | things like generics and anonymous
methods and iterators and nullable types.
| | 04:17 | Some of these things are advanced and
we won't be covering them in this course,
| | 04:21 | but we will be looking at things like
nullable types a little bit later on.
| | 04:24 | In 2007, that was when .NET 3.0 was released.
| | 04:28 | And in .NET 3.0 along came C# 3.0,
which introduced concepts such as object
| | 04:34 | initializers, anonymous types, and so on.
| | 04:37 | Again, some of these are
advanced, like lambda expressions--
| | 04:40 | we won't be looking at those--but
we will be using things like object
| | 04:43 | initializers later on.
| | 04:44 | And then that brings us to 2010, which was
when the .NET 4.0 Framework was released,
| | 04:50 | and along came C# 4.0, with things
like dynamic binding and named and
| | 04:55 | optional arguments.
| | 04:56 | And we'll be again--as you may have
detected by now, a bit of a pattern--
| | 05:00 | we will be looking at some of
those later on in the course.
| | 05:03 | Now as I mentioned earlier, C# is a compiled
language, and that means a couple of things.
| | 05:08 | In C#, you have to declare your
variables before you use them.
| | 05:12 | There's no way around this.
| | 05:14 | You have to actually say here's the
variable I'm going to use and I have to
| | 05:17 | say what type it is.
| | 05:18 | Now if you're used to a language like
JavaScript, you simply use the keyword var
| | 05:22 | to declare a variable in JavaScript.
| | 05:24 | And you can also do that
in the newer versions of C#.
| | 05:28 | But we're not going to be doing that now;
| | 05:29 | we're going to see how typing actually works.
| | 05:31 | So when you declare a variable,
you have to supply a type and supply a name.
| | 05:36 | So, for example, I would say
int myCounter or string message.
| | 05:40 | In this case, myCounter is an integer
variable for integer numbers and the
| | 05:45 | message variable is a string.
| | 05:47 | The reason you have to do this is
because it helps the C# compiler optimize the
| | 05:51 | program for knowing what kinds
of data it's going to work with.
| | 05:54 | It doesn't have to figure it out on the fly.
| | 05:56 | You can also initialize
variables when you first declare them.
| | 06:00 | I could've written, for example,
"int myCounter = 200," or "string message = "Hello World!""
| | 06:07 | And this assigns an initial value
to the variable when it is declared.
| | 06:12 | The other thing you need to know
about C# is the concept of namespaces.
| | 06:16 | Again, other languages have something like this.
| | 06:19 | In Java you may have seen
something like packages.
| | 06:22 | JavaScript doesn't really
have something like this.
| | 06:25 | There are some efforts to kind of
fake it up using things called modules.
| | 06:29 | But a namespace is basically just a way to
organize a bunch of information into classes,
| | 06:36 | and .NET uses namespace to organize
all the classes that it provides for you.
| | 06:41 | Essentially, it's a way of naming related
classes and other namespaces within the
| | 06:46 | namespace such that you can group them
together into logical formations that
| | 06:50 | make sense for various pieces of functionality.
| | 06:53 | And to take an example, .NET provides a
namespace called System, which we will
| | 06:58 | be using a lot in this course.
| | 07:00 | And inside System, there will be
classes, so just Console and Environment
| | 07:04 | and Math, and so on.
| | 07:05 | So each of those little boxes there
represents classes and the keyword System
| | 07:09 | represents the namespace.
| | 07:11 | And in fact, you and your
applications can create their own namespaces, and
| | 07:15 | we'll see that a little bit later in the
course when we start creating our own applications.
| | 07:18 | But this is an important concept to understand.
| | 07:20 | C# and .NET in general uses
namespaces to organize classes.
| | 07:25 | And this is how applications get
organized and it makes things a lot easier when
| | 07:29 | you're writing your code in C#.
| | Collapse this transcript |
| Understanding the structure of a C# program| 00:00 | Let's take a look at the
basic structure of a C# program.
| | 00:04 | Now, I've gone and fired up
the C# Express development tool.
| | 00:07 | I'm going to create a new project by
clicking the New Project link here on
| | 00:11 | the left-hand side.
| | 00:13 | The New Project dialog comes up.
| | 00:14 | Throughout this course, we're going to
be using console applications to build
| | 00:19 | our examples, because they are one of
the simplest applications to create and
| | 00:23 | they allow us to focus on just the C#
language without having to worry about all
| | 00:28 | the user-interface-related
code that other projects require.
| | 00:32 | I'm going to select the Console
Application option, and I'm going to give it a name.
| | 00:36 | I'll just call this one
StructureCSharp, and I'm going to click OK.
| | 00:45 | At this point, C# Express will create a
new project and open it for me, and it
| | 00:50 | will drop me in the editor,
into a file called Program.cs.
| | 00:53 | C# code is stored in files that have
the .CS file extension. And right now, we
| | 00:59 | only have one of these, but your application
can use as many of these files as you like.
| | 01:04 | And in fact, as you build your programs,
you'll probably create many different
| | 01:09 | .CS files to group related classes and
pieces of your code, together rather than
| | 01:14 | just type thousands of lines into one file.
| | 01:16 | For now we've only got one, so
let's go through this file line by line.
| | 01:21 | Right at the top here we
have a bunch of using statements.
| | 01:26 | These statements tell the C# compiler
which pieces of the .NET Framework that my
| | 01:31 | project will be using, and they allow
me to write my code using a bit of a
| | 01:36 | shorthand notation that we'll
see more of in a few minutes.
| | 01:41 | Now, if you're familiar with other
languages, like, say, Java or C or C++, these
| | 01:48 | using statements are sort of
analogous to things like import statements or
| | 01:54 | include statements, and so on.
| | 01:56 | But in C#, we use the using statement
to indicate which pieces of the .NET
| | 02:01 | namespaces I'm using in my program.
| | 02:04 | The next line down is the
namespace declaration for this project.
| | 02:09 | That's here on line 6.
| | 02:10 | Now, I mentioned earlier that C# uses
something called namespaces to organize
| | 02:15 | code into related groups, or
modules, and your program is no different.
| | 02:20 | Namespaces are basically
just an organizational tool.
| | 02:24 | They keep related code together,
and they prevent certain kinds of problems.
| | 02:29 | For example, if your program were to
define a class that has the same name as a
| | 02:34 | class in some other .NET library,
either from Microsoft or some other third
| | 02:39 | party, your program's namespace would
keep those two classes from colliding with
| | 02:44 | each other and causing a
whole bunch of compile problems.
| | 02:47 | Now, the C# editor creates the
namespace for you when you create your project,
| | 02:52 | and it defaults to the name of the project,
and we're just going to leave this as it is now.
| | 02:57 | Next, we have something
called a class definition.
| | 03:00 | You can see that here on line 8.
| | 03:02 | It's the keyword "class"
followed here by the word "Program."
| | 03:07 | Again, I mentioned earlier that in
C#, almost everything is an object, and
| | 03:10 | again, your program is no exception.
| | 03:12 | In C#, the way that you define and
create objects is by using the "class" keyword,
| | 03:18 | which we'll see more of later in the course.
| | 03:20 | And again, we're just going
to leave this as it is for now.
| | 03:24 | Inside the class definition is the most
important part of our C# program, the Main function.
| | 03:30 | You can see that here on line 10.
| | 03:32 | Now if you're already familiar with
languages like C, Java, Objective-C, and so
| | 03:37 | on, then this will look familiar to you.
| | 03:40 | If not, let me explain.
| | 03:41 | When .NET goes to run your C#
program, it needs to know where to start.
| | 03:46 | The Main function is that starting point.
| | 03:49 | It doesn't matter how many functions or
lines of code your application contains;
| | 03:53 | somewhere in your program .NET expects
to find one special function called Main,
| | 03:58 | and that's where it begins running your program.
| | 04:01 | It has to be written as you see it here.
| | 04:03 | It needs to be called Main, and the
first letter must be uppercase because C# is
| | 04:08 | a case-sensitive language.
| | 04:10 | Case does matter here, because if you
try to ignore case in C#, whether it's
| | 04:14 | for function names or variable names or
anything else, you are in for a bunch of problems.
| | 04:19 | Now, it's important to note that not all
C# project types have a Main function,
| | 04:25 | for example ASP.NET pages, but many of them do.
| | 04:29 | This isn't something that you'll ever
have to worry about though, because when
| | 04:32 | you're using the visual C# programming
tools to create projects, it will create
| | 04:37 | the Main function for you if it's needed.
| | 04:40 | Don't worry for now what the words
"static" or "void" mean, or the stuff that's
| | 04:45 | inside the parentheses;
| | 04:47 | we're going to cover those later.
| | 04:49 | Let's take a look at some
of the syntax rules of C#.
| | 04:51 | Now first, notice these curly braces
on line 7, and 9, 11, 12, 13, and 14.
| | 04:59 | These braces are used to group related
lines of code together in what are called
| | 05:05 | statement blocks of code.
| | 05:06 | You can see that they come in pairs.
| | 05:08 | There's an opening brace and there's a
closing brace, and they must match up.
| | 05:12 | Now, they define starting and ending
points for things like functions and
| | 05:17 | classes and loops, all of which
we will see later in the course.
| | 05:22 | If you have experience in languages
like JavaScript or C or Java, then
| | 05:26 | you've seen these before.
| | 05:27 | And if not, then all you need to know is
that they group lines of code together.
| | 05:32 | Now, you'll notice that the Main
function is empty, and that's okay, because
| | 05:35 | technically, this is a complete C# program.
| | 05:38 | But let's look at some basic
examples of C# statement syntax.
| | 05:43 | To declare a variable, I need
to specify a type and a name.
| | 05:48 | So for example, I can
type "int" and then "myVariable."
| | 05:54 | This is different from languages like
JavaScript where you don't need to specify
| | 05:59 | a type for your variable.
| | 06:01 | Now note, also, that every statement in C#
must end with a semicolon, as I've done here.
| | 06:08 | Some other languages, like JavaScript for
example, don't require this, but C# does.
| | 06:13 | Every time you type a statement,
whether it's a variable declaration or you
| | 06:16 | call a function or any kind of statement that
you write in the code, it has to end with a semicolon.
| | 06:23 | That's a really great practice because it
really makes it clear where statements end.
| | 06:28 | Now, in C#, I can use some of the
built-in .NET objects, since I've included
| | 06:33 | them in those namespaces using the using
statements--for example, the Console object.
| | 06:39 | So let me just show you a quick example.
| | 06:41 | I'm going to start typing the word
"Console," and you can see that as I'm typing,
| | 06:45 | the Visual C# Express development tool
is helping me out here by trying to guess
| | 06:50 | what it is I'm going to type, and you
can see it's centered on the word "Console"
| | 06:53 | there in the little pop-up.
| | 06:54 | So if I hit Return, it'll
put the word "Console" for me.
| | 06:58 | Console is one of the built-in
objects in .NET when you're using
| | 07:02 | console applications.
| | 07:03 | For example, to write something out
to the console, I can use the WriteLine
| | 07:07 | function. So I'm going to type dot,
and once again that little code hinter comes
| | 07:12 | up, and I'm going to start using word Write.
| | 07:14 | You can see that it zeros in on
some of the functions available to me.
| | 07:19 | I'll just choose the WriteLine function.
| | 07:23 | I will just simply write
out something like this.
| | 07:26 | Once again, notice that I've got a
semicolon at the end of my statement.
| | 07:30 | The other thing that you should
notice is that in C#, strings are contained
| | 07:35 | within two double quotes.
| | 07:37 | We'll cover a lot of this a
little bit later in the course.
| | 07:39 | But if you're coming from languages
where strings can be specified using either
| | 07:43 | single or double quotes,
that's not the case in C#;
| | 07:46 | you have to use double quotes.
| | 07:46 | Now, notice how the word
Console is in light blue.
| | 07:50 | That's because the Compiler notices
that I'm using a built-in object in C#.
| | 07:55 | The Console object is
contained within the System namespace.
| | 07:59 | Watch what happens when I go up
here and I comment out the using System
| | 08:04 | statement up here on line 1.
| | 08:05 | Notice now I've got a little red
squiggle down here on my Console object.
| | 08:11 | It says, "The name 'Console' does not exist
in the current context," when I mouse over it.
| | 08:16 | So now I've gone from being able to use this
object to not being able to use this object.
| | 08:21 | The reason for this is, when I commented
out the System namespace, if I want to
| | 08:25 | be able to use that object now, I
have to write what's called a fully
| | 08:28 | qualified path name.
| | 08:30 | So I would have to write out
"System.Console.WriteLine" if I wanted to use this
| | 08:36 | now. And you can see that when I put
the word "System" in front of the word
| | 08:39 | "Console," now it goes back to being light
blue because the compiler recognizes it again.
| | 08:43 | So by using these using statements,
I can write my code using shorthand, rather
| | 08:49 | than having to write out these big, long,
fully qualified paths to all the objects in .NET.
| | 08:55 | So it makes writing your code a lot easier.
| | 08:57 | So I'll go back up to the top
here and uncomment that line.
| | 09:03 | You notice even when I have it uncommented,
I can leave it fully qualified if I want to.
| | 09:07 | But now, I have the ability to take
out that System statement and now Console
| | 09:11 | goes back to being recognized.
| | 09:14 | White space doesn't really matter in C#.
| | 09:16 | Now, some languages consider the
indentation level of lines of code to be
| | 09:20 | important, but C# does not.
| | 09:22 | You can put as much or as little white
space in your program statements as you like.
| | 09:27 | For example, I could put this
statement all the way over here, and I can just
| | 09:31 | put this statement all the way back over here.
| | 09:33 | It doesn't really matter; this is all good.
| | 09:35 | Obviously, there are places
where white space is going to matter.
| | 09:38 | So for example, inside of a
string, if I do this, well, that's
| | 09:41 | pretty significant.
| | 09:42 | That's going to affect the way
that that string is written out.
| | 09:44 | But within lines of code,
white space does not matter.
| | 09:49 | So if you're coming from a language
where white space matters, you don't have to
| | 09:52 | worry about that here.
| | 09:53 | Indentation in C# is just
used for maintaining readability.
| | 09:58 | So we've seen enough C# where we can
now start writing our programs, and we can
| | 10:02 | go on to the next part of the course.
| | Collapse this transcript |
| Compiling and running your code| 00:00 | One last thing that we need to look at
before we jump in and start writing our
| | 00:04 | C# code and learning how to do all
kinds of great things, like writing programs
| | 00:08 | and using variables and objects and so on,
and that is compiling and running the code.
| | 00:14 | I realized I've done this a couple of
times so far, but I want to get a little
| | 00:17 | bit deeper into this.
| | 00:18 | That way, as you're working through
the course, you can see how the building
| | 00:22 | process works and the various tools
that you'll need for when errors happen in
| | 00:27 | your code. And I say when and not if
because errors are going to happen and you
| | 00:31 | need to be prepared for that and to see
how to recover from these situations and
| | 00:35 | how to build your code correctly.
| | 00:38 | So as I said earlier, C# is a compiled language.
| | 00:41 | You have to compile it before you can
run it, so we're going to cover some
| | 00:45 | tips on how to do this.
| | 00:47 | Now, the term for compiling and
creating your finished application is "build."
| | 00:52 | So let's just make a new project,
and we're going to call it BuildAndRun and make
| | 00:59 | sure it's a console application.
| | 01:01 | I'm going to click OK.
| | 01:03 | Now, what I'm going to do first is I'm
going to click the Save All icon here.
| | 01:09 | I can also just choose
Save All from the menu here.
| | 01:12 | I'm going to save this
application in my Documents folder.
| | 01:16 | Now, this folder will be different for
you based upon the computer that you're
| | 01:20 | using and where your Documents
folder is, but I'm going to save it in the
| | 01:23 | default location, which is the visual
studio 2010/Projects folder, and we'll go
| | 01:28 | out to the file system and
see this in just a minute.
| | 01:30 | But I'm going to save.
| | 01:33 | Now that I've saved it,
I've actually put the project onto a physical
| | 01:38 | location on my disk.
| | 01:39 | It's no longer sitting out
there in temporary space.
| | 01:42 | So recall that the way that we build
that application is by using either F6, or
| | 01:46 | up here in the Debug menu,
we can choose Build Solution.
| | 01:50 | So I'm going to choose Build Solution
and you can see down here in the toolbar,
| | 01:54 | there's a little message
that says "Build succeeded."
| | 01:57 | So let's go out to the file system and see
where the application is actually built to.
| | 02:03 | I'm here in my Documents folder,
and you can see that there's a folder here
| | 02:07 | called Visual Studio 2010.
| | 02:09 | This might be slightly different
based upon which version you're using.
| | 02:12 | But I'm going to go into Visual Studio 2010.
| | 02:15 | There's a folder called Projects.
| | 02:17 | Here's the project that I
just built called BuildAndRun.
| | 02:20 | So let's take a look in there.
| | 02:21 | You'll see that inside BuildAndRun,
this is the solution, the top-level project
| | 02:25 | for our code, and then there's a
folder that goes along with it.
| | 02:29 | And inside the folder,
there's the Program.cs file.
| | 02:32 | This is where our code is kept.
| | 02:34 | This is the project file.
| | 02:35 | There's also a folder in here called bin.
| | 02:38 | bin is short for binary.
| | 02:40 | This is where the application is kept.
| | 02:42 | Inside there, there are two folders:
| | 02:43 | there's Debug, and there's Release.
| | 02:46 | If we look in the Debug folder, you'll
see that there's some information here
| | 02:50 | about the application's debug information.
| | 02:53 | If we go into the Release folder, you'll
see that there's a couple of things in here.
| | 02:57 | First, there is BuildAndRun, and you
can see that that's an application.
| | 03:00 | This is the actual finished
application that gets built when you create the
| | 03:05 | application using Build
inside the C# Express environment.
| | 03:08 | So this is the finished application.
| | 03:10 | That little PDB file is
called the program database.
| | 03:14 | It contains some information that .NET
needs to use in order to debug and run
| | 03:18 | the application that we've built.
| | 03:20 | But for now, all you need to know is
that when you build an application, this is
| | 03:24 | where it actually gets placed.
| | 03:25 | When you create a project and you save
it in whatever folder you save it in, the
| | 03:29 | C# IDE will build this
subfolder structure for you.
| | 03:34 | Let's go back to the IDE.
| | 03:36 | Now, we're going to take a look at how
we can build errors and warnings and fix
| | 03:42 | things and so on like that.
| | 03:43 | Here in my Main function, what
I'm going to do is write some code.
| | 03:48 | I'm going to say int myInt = 50.
| | 03:55 | Don't worry too much about
following along with this code.
| | 03:58 | We're going to cover variables and stuff later.
| | 04:00 | I'm going to make one more line.
| | 04:08 | This is code that we've been working with
in a couple of examples now. Let me save this.
| | 04:14 | Now, I'm going to hit F6, and you can
see that everything built just fine.
| | 04:18 | However, you can see that there's
a little squiggle here under myInt.
| | 04:21 | What I'm going to do is go up to the
View menu, and in Other Windows, I'm going
| | 04:29 | to choose Error List.
| | 04:31 | When I choose the Error List, you can
see here that there is a warning, and the
| | 04:35 | warning is that the variable myInt is
assigned, but its value is never used.
| | 04:40 | Warnings are not necessarily as bad as
errors; your application will still run
| | 04:44 | just fine without it.
| | 04:46 | And just to show it to you, let me
you put one more line of code in here.
| | 04:54 | Now, when I press F5 to run the
application, or if I choose this little
| | 04:58 | triangle up here, or if I go to the
Debug menu > Start Debugging--that's
| | 05:03 | where I run the program; I'll just use F5--
| | 05:06 | you can see that the program ran just
fine, even though I had a warning there.
| | 05:09 | But that's no excuse for having warnings.
| | 05:12 | If you've got a warning somewhere in
your code, you should really pay attention
| | 05:15 | to it because the compiler is
trying to tell you something.
| | 05:18 | And in this case, the
warning is a little bit benign.
| | 05:19 | I just created a variable that I never used.
| | 05:22 | But warnings can actually be pretty
serious, and they usually indicate something
| | 05:25 | is wrong with your code.
| | 05:26 | So if you get warnings in your code, go look
them up in the error list here and go fix them.
| | 05:30 | The next thing I want to do is make an error.
| | 05:34 | So what I'm going to is I'm going to
remove the double quotes from the end
| | 05:38 | of that line there.
| | 05:40 | You can see that when I do that, I get
a red squiggle which says that there's
| | 05:44 | some kind of error going on.
| | 05:45 | And if I try to hit F6, there's
a whole bunch of build errors.
| | 05:50 | You can see down in the error list,
| | 05:53 | there are now three errors and the
warning for the variable that I had before.
| | 05:57 | You can see that the errors are hey!
| | 05:59 | There's a new line in the constant.
There is no semicolon.
| | 06:01 | There is no closing parenthesis.
| | 06:04 | All of these errors are occurring
because I left off that closing quote.
| | 06:08 | When you get an error like this and
the error list pops up, you can just
| | 06:11 | double-click on any one of these guys,
and it will take you right to the line
| | 06:15 | where the error occurs.
| | 06:17 | Now, in this case to fix this, I
just need to put the double quotes back.
| | 06:21 | But if I don't do that and I leave it
and I ignore these warnings and I try to
| | 06:25 | run, by pressing F5, you'll
see that there are build errors.
| | 06:29 | And C# is telling me, hey!
| | 06:30 | There were build errors, but if you like,
you can continue and run the last time
| | 06:35 | that this was successful.
| | 06:36 | But I'm not going to do that.
| | 06:37 | What I'm going to do is click No and
I'm going to say, okay, let's go ahead and
| | 06:40 | fix that problem, so
I'll put the quotes back in.
| | 06:42 | Now everything is fine.
| | 06:45 | Once I press F5, you can see
that the code is now working again.
| | 06:49 | The next thing I want to do is see away
that I can get more information about my build.
| | 06:55 | Under the Tools menu, I'm going
to switch over to Expert Settings.
| | 07:00 | Don't be intimidated;
this really isn't a very big deal.
| | 07:03 | What I'm going to do is choose the View menu.
| | 07:07 | I have the Error List still, but now
I have a new window here under Expert
| | 07:11 | mode called Output.
| | 07:12 | You can see that when I
choose it, there it is right there.
| | 07:15 | So the Output window shows me a lot
more detailed information about the
| | 07:18 | build-and-run process.
| | 07:20 | So, for example, if I now hit F6, you'll
see that the output window is giving me
| | 07:24 | a whole bunch of information about the
files that got compiled, any warnings or
| | 07:28 | errors that popped up.
| | 07:29 | You can see that whether
the build succeeded or not.
| | 07:32 | You can see that where the
output of the application was built.
| | 07:36 | You can see that BuildAndRun.exe was
placed in this path down here at the bottom.
| | 07:40 | By using the Output window, you can get
more information about where the build
| | 07:44 | process is and what it's
doing and what the results are.
| | 07:48 | The last thing I want to do is
show you how you can find out more
| | 07:51 | properties about your project.
| | 07:54 | Under the Project menu, I'm going
to choose BuildAndRun Properties.
| | 07:58 | This menu item will change based
upon whatever your project is called.
| | 08:02 | It'll be project name and
then the word Properties here.
| | 08:05 | When I choose this, I get a whole bunch
of properties about what my program is
| | 08:09 | and how it's being built.
| | 08:11 | So here under the Application tab, I can
see that this is what my Assembly name is.
| | 08:16 | An assembly is basically just a
generic term that says this is some physical
| | 08:20 | piece of code on the disk
somewhere and it's the name of my project.
| | 08:23 | Same thing for the namespace.
| | 08:25 | I can also see what target
framework I'm going after.
| | 08:28 | In this case, I'm using the .NET Framework 4.
| | 08:31 | But if I click on this, you can see I
can build my application to target other
| | 08:34 | versions of the .NET Framework, all the
way from 2.0 up through 3 and through 4,
| | 08:39 | and there are other
frameworks I can install as well.
| | 08:42 | Under the Output type dropdown, this
controls what kind of application I'm building.
| | 08:46 | Now, it's currently set to be a console
application, but I can change it to be a
| | 08:49 | Windows app or a class library, and so on.
| | 08:52 | The last thing I want to show you is
under Build, there are ways that I can
| | 08:57 | control how the application is built.
| | 09:00 | We'll see a little bit of these later
on, but I can change how the errors and
| | 09:04 | warnings are reported.
| | 09:05 | I can say what the warning level is
and there are four warning levels, all the
| | 09:09 | way up from very verbose down to not
very detailed at all. So I can choose what
| | 09:13 | warning level I want.
| | 09:14 | I'm going to leave it on 4.
| | 09:15 | I can also suppress individual
warnings that I don't want to know about.
| | 09:19 | Now, I don't suggest that you do this,
because it's really good idea to know
| | 09:23 | about all the warnings in your
code, but it is possible to do this.
| | 09:27 | You can also set a little preference over
here that says Treat warnings as errors.
| | 09:31 | I can say None or All or Specific warnings.
| | 09:34 | If I changed this to All, for example,
and then went back to my application,
| | 09:40 | you can see that when I hit up 6,
now the warning that was hey!
| | 09:44 | The variable 'myInt' is assigned, but its
value is never used, it's an error now.
| | 09:48 | It's no longer a warning.
| | 09:50 | So I'm going to go back and
change that back to the way it was.
| | 09:55 | Now, I'm going to hit F6, and you can
see that we're back to being a warning.
| | 10:00 | This is how you can control how your
application is built, and it's how you get
| | 10:04 | more information about the process
by which Visual C# Express builds your
| | 10:08 | application and runs it and fixes errors.
| | 10:11 | Now that you know how applications are
actually built, we can dive right in and
| | 10:15 | start doing some more interesting stuff.
| | Collapse this transcript |
|
|
3. Program FlowReading and writing from and to the Console| 00:00 | So now that we've got the foundational
stuff out of the way, we can dive in and
| | 00:03 | start writing some real C# code.
And what we're going to do in this particular
| | 00:07 | example is see how to read information from,
and write information to, the console window.
| | 00:14 | And this is important to know how to do
because for the rest of the course
| | 00:17 | we're basically going to be building
examples that use the console as the place
| | 00:21 | where we write information
to and read information from.
| | 00:24 | So we need to get a fundamental understanding
of how the console works in order to do that.
| | 00:28 | So I've opened up, under Chapter 3, the
HelloWorldProject in the example files
| | 00:33 | folder. And if you don't have that, you can
just simply create a new project and follow along.
| | 00:38 | The other thing I've opened up is the
ExampleSnippets.txt file, and this contains
| | 00:44 | the code that I'm going to be copying
and pasting from so that you don't have to
| | 00:47 | sit there watch me type.
| | 00:49 | So let's go back to the program. You can
see that we have our HelloWorldProject,
| | 00:54 | and down here in our Main function, this is
where we're going to be filling the code in.
| | 00:58 | So let's go ahead and do something
really simple, which we've already done a
| | 01:02 | couple of times, but just for refresher,
let's write some information out to the console.
| | 01:05 | So I'm going to copy this line right here
that says Console.WriteLine. I'm going to paste that in.
| | 01:12 | So the console object has a series of
functions that read and write data, and the
| | 01:17 | most common ones are WriteLine and
ReadLine. And you can guess what they do.
| | 01:21 | WriteLine writes out a string of text
followed by a carriage return, which takes
| | 01:26 | the cursor back to the new line.
| | 01:28 | Now we could use Write which writes out
the string and does not put a carriage
| | 01:31 | return on there, but for readability,
we'll just WriteLine. And then there is the
| | 01:35 | ReadLine function which reads a string of text.
| | 01:39 | In this case, I'm using it just to
keep the console window up, so you can see
| | 01:42 | the example working, but it will
return a string if we want it to.
| | 01:46 | So let's just go ahead and save this, build it--
| | 01:49 | you see the Build succeeded--and run it,
and no surprise, the string "Hello World!"
| | 01:55 | gets written out to the console.
| | 01:56 | So let's go ahead and make
a couple of changes here.
| | 01:59 | What I'm going to do now is go back to
the Snippets, and this time we're going to
| | 02:03 | read information from the
console window and then write it out.
| | 02:08 | So I'm going to copy these
three lines, paste them in.
| | 02:13 | So now what we're going to do is write
out a string that says, "What is your name?"
| | 02:18 | And then we're going to use the
ReadLine function to read a string of data from
| | 02:22 | the console and then write out a
message that says, "Hello there" plus whatever
| | 02:27 | name the person gave us.
| | 02:28 | So you can see here that we've got a
string variable that is being assigned to
| | 02:32 | the result of the ReadLine function.
| | 02:35 | Down here, we're just not using
the result, which is why the window is
| | 02:38 | staying up. But here we're actually going to
read the result and use it in the next string.
| | 02:43 | So I'm going to save, I'll build, and we'll run.
| | 02:47 | You can see it says,
"Hello World! What is your name?"
| | 02:49 | And I'm going to type in "joe," hit
Return and it says, "Why, hello there joe."
| | 02:54 | Let's go take and look at the
code and see why that works.
| | 02:56 | You can see that the string variable
here that gets returned from ReadLine
| | 02:59 | contains my name, and then in the
WriteLine statement we're writing out the
| | 03:04 | string "Why, hello there" and
then plus the string here.
| | 03:09 | Writing strings out to the
console window takes many forms.
| | 03:12 | It's something that you'll probably do a bunch.
| | 03:14 | And although you can use the plus
operator, there is actually other ways
| | 03:17 | to write strings out.
| | 03:18 | So let's take a look at how those work.
| | 03:21 | To build strings in C# for the purposes
of displaying to the user or formatting
| | 03:26 | them for output, there is a
couple of ways you can do this.
| | 03:28 | Now you've already seen the
example where we use the plus operator.
| | 03:31 | This is something that you're probably
familiar with if you done this in JavaScript.
| | 03:35 | It works in JavaScript and as you've seen,
| | 03:36 | it works in C# too.
| | 03:38 | However, it's not the most
efficient way to build strings in C#, for
| | 03:42 | reasons we'll see later on.
| | 03:43 | There are other ways to format strings
for display to the user, and the way that
| | 03:48 | we do that is by using the String.Format method.
| | 03:52 | And that method takes an argument,
which is the string you want to write out
| | 03:55 | along with data that you
want to put into that string.
| | 03:59 | So for example, if we wrote String.Format,
| | 04:02 | "There are," and then some code that
we'll get back to in a second, "seconds in a
| | 04:07 | year" and then an argument,
which is probably a number.
| | 04:11 | The way that you format a string is by
using those curly braces with an integer
| | 04:15 | number in there that serves as a
placeholder for data that's going to be
| | 04:19 | inserted into the string for you.
| | 04:21 | And as you might have guessed, if you
had more than one piece of data you wanted
| | 04:24 | to do this with, you would
use more than one curly brace.
| | 04:28 | So in this example, it says String.Format.
| | 04:30 | There are something seconds in a
year, and that little i is going to be
| | 04:34 | substituted where the 0 is in
those curly braces--and in fact, it
| | 04:38 | substitutes entire thing.
| | 04:39 | The curly braces and the 0 don't
appear in the finished string;
| | 04:42 | it gets substituted with the value of the data.
| | 04:45 | If you had more than one, you'd simply
use more than one curly brace, and you'd
| | 04:48 | increment the number for
each one of the variables.
| | 04:51 | So in this case, if I had two arguments
that I wanted to format into the string,
| | 04:55 | I would simply supply those as arguments
and use two sets of curly braces in the
| | 04:59 | String.Format argument.
| | 05:01 | So let's go back to the
code and see how this works.
| | 05:03 | So I want to go back to my Snippets,
and I'm going to copy this line right here.
| | 05:07 | Now I'll paste it in.
| | 05:12 | So now we have a variable called
mySeconds, which we are calculating.
| | 05:15 | So there is 60 seconds in a minute,
times 60 minutes in an hour, times 24
| | 05:20 | hours in a day, times 365 days in a
year, and that gives us the number of
| | 05:25 | seconds in one year.
| | 05:26 | So you can see here that we have our
Console.WriteLine, and we have our string
| | 05:31 | with the curly brace.
| | 05:32 | Now notice we're not using the
String.Format method, and that's because the
| | 05:35 | WriteLine method of the console object knows
how to use the String.Format method internally.
| | 05:41 | So we pass it what is called a
format string, which has this little escape
| | 05:45 | sequence, or code sequence in it.
And we're passing in the mySeconds variable and
| | 05:50 | when we run this, if everything goes well,
then we should have the number that's
| | 05:53 | calculated inserted into the string.
| | 05:55 | So let me go up here and just comment out
the code that we're not using, and we'll save.
| | 06:03 | This time I am also not going to use F6;
| | 06:05 | I'm just going to hit F5, which
builds the program for me and runs it.
| | 06:11 | So I'm going to collapse two steps
down to one and press F5 and you can see
| | 06:16 | that the number of seconds in one year
has been substituted where those curly
| | 06:20 | braces were in the string.
| | 06:22 | We were going to be using
Console.WriteLine and Console.ReadLine to write and
| | 06:27 | read information to the
console throughout this course.
| | 06:30 | And after following the example here,
you can see how to do it for yourself.
| | Collapse this transcript |
| Writing conditional statements| 00:00 | One of the things that any application
has to be able to do is make decisions.
| | 00:05 | Decisions are inescapable.
| | 00:07 | They are an important part of
pretty much any nontrivial program that
| | 00:11 | you're ever going to make.
| | 00:12 | Decisions are made when your program
flow is chugging along nicely and suddenly
| | 00:16 | you come into a situation where you
have to make a decision, and there is also
| | 00:19 | the decision of either true or false.
| | 00:22 | And this is, of course, built in
classical programming using the if statement.
| | 00:26 | The if statement takes a Boolean
condition and if that condition is true then
| | 00:31 | the code that is inside
the if statement is executed.
| | 00:35 | Now, of course, there is a case for when the
condition is not met, and that is the else case.
| | 00:40 | If the condition is not met and you
have an else case on your if statement,
| | 00:43 | because they are after all optional,
then the code for the condition where the
| | 00:48 | condition is not met is run instead.
| | 00:50 | In C# you can also have the else if
statement, so we could replace that else
| | 00:55 | with an else if on another condition.
| | 00:57 | And in fact we can chain a bunch of
these together to make a whole bunch of if,
| | 01:01 | else if, else if, else if, and so on.
And if you want, you can have a trailing
| | 01:06 | else condition to handle everything else.
| | 01:08 | So let's jump over the
code and see this in action.
| | 01:11 | Here in the code, I've opened up my
ConditionalCode example file, and I've got my
| | 01:16 | Program.cs code open.
| | 01:18 | I've also got the ExampleSnippets file
open right here. And I'm going to scroll
| | 01:22 | down to the Conditional Statements
section, because these are the statements
| | 01:25 | that we're going to be using.
| | 01:27 | So back over here in the code, let's put
together an if statement and see how it works.
| | 01:32 | So I'm going to copy these lines right
here in my variable declaration, along
| | 01:38 | with the if statement. I'll copy
and we'll just paste that in.
| | 01:44 | And you can see here that we have a
variable, named theVal, which is initialized
| | 01:48 | to be 50, and then we have an if
statement, which tests the condition to see if
| | 01:53 | (theVal == 50) then run some code.
| | 01:57 | Notice that there is two equal signs in here.
| | 02:00 | If I just tried to put one equal
sign in here, I would get an error.
| | 02:04 | You can see the little red squiggle
shows up, and it says, hey, you can't do a
| | 02:07 | conversion. And it's not
important what that error means;
| | 02:10 | the point is that you can't do that.
| | 02:12 | So to test for equality it's two equal signs.
| | 02:15 | One equal sign does assignment;
two equal signs tests for equality.
| | 02:20 | So if (theVal == 50) then we'll write
out this data, so it's firstVar is 50.
| | 02:27 | And actually, let me change that because
it's misspelled. There we go; theVal is 50.
| | 02:32 | So we'll save this, and we'll run it.
| | 02:34 | I'll use F5 to do that. And you can
see that "theVal is 50" is being written out.
| | 02:40 | So let's go back to the
code and change the value.
| | 02:43 | Let's make it 51,
and we'll save and run it again.
| | 02:47 | And you can see this time nothing
is being written out because the
| | 02:50 | condition is not being met.
| | 02:51 | Let's go back to the code.
| | 02:53 | Let's change this back to 50.
| | 02:54 | The other thing I want to point out on
the if statement is you'll notice that
| | 02:58 | I'm using these curly braces to
contain the code that's being executed in the
| | 03:02 | case of the if condition.
| | 03:04 | If all you have is one line of code
for your if condition, you actually can
| | 03:09 | technically leave these braces
out and that will work just fine.
| | 03:13 | However, for the sake of readability,
and because if statements are very rarely
| | 03:19 | limited to one line, I always use the braces.
| | 03:21 | I always put them in there.
it's a good idea to do so.
| | 03:24 | It helps readability of code.
| | 03:25 | It helps keeping your statements together.
| | 03:27 | So my suggestion is to always use the
curly braces, even if you only have one line.
| | 03:32 | Let's go back to the Snippets, and let's
bring a couple of other lines in here now.
| | 03:38 | We're going to try the
else if condition this time.
| | 03:42 | So I'll copy this,
and we'll paste it in below the if.
| | 03:46 | So now we have a condition that says
if (theVal == 50) then write out this
| | 03:50 | statement; otherwise else if it's 51,
write out something else. And once again,
| | 03:54 | I'll just change that.
| | 03:56 | Okay, so let's run this.
| | 03:57 | Okay, so you can see that the
first condition is being met.
| | 04:02 | Now let's change it to 51,
save and run, using F5.
| | 04:09 | And you can see that this time the else
if condition ran, because the value was
| | 04:14 | 51 instead of the 50. So this time, this
condition was executed instead.
| | 04:18 | One more test to try.
| | 04:20 | Let's go back and copy this code over.
| | 04:23 | I'll now copy this and paste at the
bottom of my else. And in this case, this
| | 04:32 | code is going to run when
none of the conditions are met.
| | 04:36 | So we have if (theVal == 50), else if
(theVal == 51), and the last else condition
| | 04:41 | catches everything else.
| | 04:43 | So let's just change this to, I
don't know, something like 75.
| | 04:46 | We'll save and hit F5.
| | 04:49 | And you can see that in this case
"theVal is something else" is being written
| | 04:52 | out, because the last else condition
is triggering because the value was not
| | 04:56 | equal to 50 or not equal to 51.
| | 04:58 | So none of these if conditions right here fired.
| | 05:02 | You can have more than one
condition in the if statement.
| | 05:06 | So for example, if I wanted to have
this if condition execute if theVal was
| | 05:11 | equal to 50, or something else, I would
simply put this one in parentheses,
| | 05:17 | and then I would use the OR operator, which
is the two vertical bars--and we'll learn
| | 05:24 | about this a little bit later,
but just bear with me for now.
| | 05:27 | So if ((theVal == 50) or (theVal == 49))
then you can write out "theVal is 50 or 49."
| | 05:39 | We'll save and now this if condition
will execute if theVal is equal to one
| | 05:45 | of those two numbers.
| | 05:46 | So we'll change it to 49, hit F5,
and you can see that the first if condition is
| | 05:51 | now being set, so that code is executing.
| | 05:55 | Let's go back. If we wanted to change
it to AND instead of OR, I am going to
| | 05:58 | just use two ampersands.
| | 06:00 | Again, we'll learn about that in a
little bit. But just for sake of example, I
| | 06:03 | want to show you how this works.
| | 06:05 | Now in this case, theVal
is something else. Why?
| | 06:08 | Because here theVal is 49, but for
this entire condition right here to be
| | 06:12 | true, both of those statements have to be true:
theVal has to be 49 and theVal has to be 50.
| | 06:19 | And since that's clearly impossible,
that for statement is not going to execute.
| | 06:23 | So you can see here that we're
using if statements to create tests for
| | 06:27 | conditions in our code, and we can chain
a whole bunch of these things together
| | 06:31 | using if, else if, and else. But if
you find yourself running into situations
| | 06:36 | where you have a lot of different
conditions to test for, using the whole bunch
| | 06:39 | of ifs and else ifs gets really hard
to read and really hard to manage, and
| | 06:44 | there's a structure for doing that
which we'll take a look at in a little bit.
| | Collapse this transcript |
| Using the switch statement| 00:00 | For cases where your code has to check a
lot of different conditions in order to
| | 00:05 | execute different parts of your code,
it's usually not very efficient to have a
| | 00:08 | whole lot of if and else if statements.
| | 00:11 | It makes the code harder to
read, and in that particular case
| | 00:14 | it's usually better to use
something called the switch statement.
| | 00:17 | And the switch statement can be
thought of as a whole bunch of if and else if
| | 00:21 | statements, but with a
slightly different way of writing it.
| | 00:25 | The way you use a switch statement is
you write the word "switch" and there is a
| | 00:29 | value that you pass to the switch
statement, and then inside the switch
| | 00:34 | statement, you use a whole bunch of cases.
| | 00:36 | So you have a case for some value, which
will then run some code, and you have a
| | 00:41 | break statement which says okay that's
the end of this case. And then you can do
| | 00:45 | this as many times as you need it.
| | 00:46 | So you can have a case for a whole
bunch of different values that all
| | 00:49 | run different code.
| | 00:50 | Now in the case where none of the
values map to a particular case, you can
| | 00:55 | have a default case, which
will run some code, or do nothing--
| | 00:59 | it's up to you. But the default
case will be executed when none of the
| | 01:03 | other values match.
| | 01:04 | Now if you're coming from some other
languages like C or Objective-C, for
| | 01:08 | example, they let you do things like this.
| | 01:10 | You can take that break statement out,
in which case, when value1 or valueN are
| | 01:16 | met, the code will run.
| | 01:18 | And in the case of value1, the code for
value1 will run as well as the code for
| | 01:23 | valueN, because there is no
break statement in there to stop it.
| | 01:26 | Now, this is not legal in C#.
| | 01:29 | In C#, every case has to
have a break command at the end.
| | 01:33 | Your code can't fall through to
next case like in some other languages.
| | 01:38 | And the reason for this is because
the designers of C# did a whole bunch of
| | 01:42 | studying of where bugs come
from in programming logic.
| | 01:45 | And it turns out that a lot of bugs can
be traced back to developers mistakenly
| | 01:49 | leaving out break statements in their
switch cases when they probably shouldn't have.
| | 01:54 | So the C# language enforces this.
| | 01:56 | You have to have a break at the
end of each one of your cases.
| | 02:00 | There is ways to get around this,
but they're kind of esoteric, and I'm not
| | 02:02 | going to show you how to do them in
this course, because they're not good
| | 02:04 | programming practices.
| | 02:05 | Just suffice it to say that you have
to have a break at each one of your cases.
| | 02:10 | So let's go ahead over to the code
and see how a switch statement works.
| | 02:12 | Here I have my SwitchStatement
project open, and in my ExampleSnippets, I've
| | 02:18 | scrolled down to my Switch area.
| | 02:20 | So what I'm going to do is copy some
code. I'll just copy the first part of the
| | 02:25 | switch case here, and I'll paste it
in, and I'll close off the switch right
| | 02:32 | there, and I'll save.
| | 02:33 | So in this case, what we're going to do
is write some code that does pretty much
| | 02:37 | the same thing that a whole bunch of
if else statements would do, but using
| | 02:41 | switch case instead.
| | 02:43 | So here you can see I've got an
integer variable called theVal, and it's being
| | 02:47 | set to a value of 50. And then the
switch statement says hey what's the value of
| | 02:52 | theVal? And for case of 50, the
Console will write line, The value is 50.
| | 02:59 | So let's save this and run it, and you
can see, sure enough, "The value is 50"
| | 03:03 | is being written out.
| | 03:04 | So if we go back and change it to, say,
something like 51 and we save that and run it,
| | 03:08 | well, now nothing is happening.
| | 03:10 | Okay, let's go back to the
code and make some changes.
| | 03:13 | Go back to my Snippets, and I'm
going to copy the rest of the cases in.
| | 03:17 | I'll save that, and now you can see
that we have a whole bunch of cases:
| | 03:24 | there is 50, 51, 52, and a default case.
| | 03:28 | So in the case where I change theVal to
be 52, then I save it, and then I run it,
| | 03:34 | in that case, the case for 52 is being run.
| | 03:37 | If I change it to something else, say
99 in this case, none of these cases is
| | 03:43 | going to match, so the default case
should be run instead. And sure enough, that's
| | 03:47 | exactly what's happening.
| | 03:49 | So let's see what happens when you
try to take out this break right here.
| | 03:52 | And you can see that when I take out
the break, the little red error squiggle
| | 03:57 | appears under this case. And specifically,
it says, "Control cannot fall through
| | 04:01 | from one case label to another."
| | 04:03 | So you can see here that C# is
explicitly enforcing the rule that you have to
| | 04:08 | have breaks in your cases.
| | 04:09 | So let me just undo that, and we'll save,
and we'll run it again, and you can see
| | 04:14 | that everything is working just fine.
| | 04:16 | So the switch statement provides a
pretty handy replacement for a whole bunch
| | 04:21 | of nested if else, and I think you can
agree with me that reading code that
| | 04:25 | looks like this with a whole bunch of
cases is a lot nicer than reading a whole
| | 04:29 | bunch of ifs and elses.
| | Collapse this transcript |
| Using operators and expressions| 00:00 | Any nontrivial program that you
write is going to be full of calculations.
| | 00:04 | You are going to be calculating things like
scores and prices and all kinds of things.
| | 00:08 | And in order to do that, you need
expressions, and you need operators to
| | 00:12 | build those expressions.
| | 00:14 | An expression is essentially just a
collection of operators and operands, which
| | 00:19 | are the things that operators
work on, that produce a result.
| | 00:23 | So for example, if we had an
expression like this, we had 5 + 2 * the absolute
| | 00:29 | value of x, that is an expression.
| | 00:32 | And the plus and the star, those are operators.
| | 00:37 | Operators are simply symbols and functions
that determine how expressions are evaluated.
| | 00:43 | So for example, we of course
have the arithmetic operators.
| | 00:47 | These are pretty common in
almost every programming language.
| | 00:49 | There's addition, subtraction, division,
multiplication, and the percent sign--
| | 00:54 | maybe something you have not seen before,
| | 00:55 | but it exists in a lot of other
languages, like C and JavaScript and
| | 00:59 | Objective-C and C++.
| | 01:01 | It's the remainder, or modulus, operator.
| | 01:04 | Basically it gives you the
leftover results of a division operation.
| | 01:10 | So for example, 5 modulus 2 would be 5
divided by 2 but what's left over, so it would be 1.
| | 01:16 | There's also the assignment operator.
| | 01:19 | The assignment operator is the equals sign.
| | 01:21 | So take an example: if we had two
variables, x and y, and we wanted to add them
| | 01:26 | together using the plus
operator, or the addition operator,
| | 01:29 | we can then take the result of that
expression and assign it to a third variable
| | 01:33 | called result, using the equal sign.
| | 01:36 | If we had a variable named distance
and we wanted to add a number to it, we
| | 01:40 | could do distance = distance + 10.
| | 01:43 | This takes the existing variable, adds 10 to
it, puts the result back in the same variable.
| | 01:49 | In fact, this is so common that there
is a shorthand notation for doing this.
| | 01:53 | You can write distance = distance + 10
the same way by just doing distance += 10.
| | 01:59 | And in C# that means, take the
variable and add to itself the number on
| | 02:04 | the right-hand side.
| | 02:05 | It also works of course for the minus,
the multiplication, the divide, and the
| | 02:10 | modulus operators as well.
| | 02:11 | In addition to the math operators,
there are also comparison operators.
| | 02:16 | So for example, we can check to see if
things are equal to or not equal to each
| | 02:21 | other by using the equality check operators.
| | 02:23 | The two equal signs
together say, hey, is a equal to b?
| | 02:27 | Do they have the same value?
| | 02:29 | We can check for things that are not
equal by replacing the first equal sign
| | 02:33 | with an exclamation point.
| | 02:34 | In this case, this says a not equal to b. And
as you might expect, there are also
| | 02:39 | operators for comparison testing to see
if there are a larger or smaller numbers.
| | 02:44 | We can do things like a > b,
a < b, a >= b, and a <= b.
| | 02:54 | The logical operators, such as AND
and OR, allow you to combine more than
| | 02:55 | one condition.
| | 03:01 | So, for example, the AND operator, we
can use to see if a=b and c=d. We use
| | 03:09 | two ampersands together.
| | 03:10 | There is no space in there.
| | 03:11 | We just put them next to each other
and that is a logical AND operator.
| | 03:15 | We can do the same thing for OR.
| | 03:17 | The OR operator is just two vertical bars.
| | 03:20 | So in this case, if a=b or c=d,
then the code inside those curly
| | 03:26 | braces would execute.
| | 03:27 | We can also do a NOT operator.
| | 03:30 | The NOT operator you can place in
front of any Boolean expression to produce
| | 03:35 | the opposite of what that value evaluates to.
| | 03:38 | So for example, in this case, we
are saying if not some Boolean value.
| | 03:43 | So if we set a to true for a certain
Boolean value, then if we use bool b = !a,
| | 03:50 | that gives us the inverse
value of a. So b is now false.
| | 03:54 | That's what the NOT operator does.
| | 03:56 | There are also operators for
incrementing and decrementing, because again, this
| | 03:59 | happens a lot in programming.
| | 04:01 | The increment operators are, as you night
expect, the addition operator, where you
| | 04:05 | simply take a and add 1 to itself.
| | 04:07 | We've already seen how to reduce that
down using shorthand notation, to take the
| | 04:11 | value of a variable and add a value to itself.
| | 04:14 | But there's even a shorter hand way of
doing this, because this is so common.
| | 04:18 | So there's the ++, and the ++
operator, postfix and prefix.
| | 04:24 | So when the ++ comes after the
variable, that's postfix; and when ++ comes
| | 04:29 | before the variable, that's prefix.
| | 04:31 | They both do the same thing:
| | 04:33 | they both add 1 to whatever the
variable is. But they do it in a certain way
| | 04:38 | that's slightly different from each
other, and we'll see why in just a moment.
| | 04:41 | As you might expect,
there's also decrement operators.
| | 04:44 | So for a + 1, we also have a = a - 1.
| | 04:48 | And we've already talked about
how we can do the -= operator.
| | 04:51 | But there's also post and prefix
versions of decrement as well, where you
| | 04:55 | simply put two minus signs next to
the variable rather than two plus signs.
| | 04:59 | So what's the difference there?
| | 05:01 | The difference is this:
| | 05:02 | Suppose we had a variable whose value is 10.
| | 05:04 | If we use this statement,
Console.WriteLine ("The value of a is:
| | 05:08 | and using our string formatting, we
put the value of a into that replacement
| | 05:13 | curly braces expression there, the ++
prefix notation would execute first before
| | 05:20 | putting the value into the string.
| | 05:22 | So in this case, the output would be
11, because a gets incremented before it
| | 05:27 | gets put into the value of those curly braces.
| | 05:30 | If we use the postfix notation,
that increment would get done after the
| | 05:35 | substitution took place.
| | 05:37 | So in that case, the output would be 10,
even though a would then be incremented
| | 05:42 | and would be equal to 11.
| | 05:44 | So that's the main difference
between prefix and postfix increment.
| | 05:47 | There's also type testing operators.
| | 05:49 | There's the is operator and the as operator.
| | 05:53 | And we'll learn more about these as we go
through the object-oriented part of the course.
| | 05:57 | But essentially, what happens here is
the is operator returns true if a given
| | 06:02 | object is a certain type.
| | 06:04 | The as operator takes a given
object and converts it to another type if
| | 06:09 | it's possible to do so.
| | 06:10 | So let's just take a quick example--and
I understand if you don't follow along
| | 06:14 | right away with this, but as we get to
the chapter on object orientation, this
| | 06:17 | will become more clear.
| | 06:19 | So suppose we had a
function that takes an object,
| | 06:21 | a generic object type.
| | 06:23 | We can say something like if obj
is the type of Employee object.
| | 06:29 | So the is operator will return true
if the object is of type Employee.
| | 06:34 | And if that's the case, we can then use
the as operator, which will convert the
| | 06:39 | object to the type that we give it.
| | 06:41 | And if it can't be done, it will return null.
| | 06:44 | So in this case, we are taking the
Employee emp and we are saying obj as Employee.
| | 06:50 | So it's converting the obj to an
employee object which we can then operate on.
| | 06:55 | There's also an operator
called the ternary operator.
| | 06:57 | Now most operators we have seen
so far are binary operators.
| | 07:00 | So for addition, for
example, you have two operands.
| | 07:03 | You have the two operands
that are being added together.
| | 07:05 | The ternary operator works
a little bit differently.
| | 07:08 | It actually has three operands, and it's
written using the question mark and the colon.
| | 07:13 | It operates as if it were a
very compact if else statement.
| | 07:18 | So it works like this:
| | 07:19 | You have a condition which evaluates to
true or false just like any other statement.
| | 07:24 | You then put the question mark next to
it and then the value that you want to
| | 07:29 | be assigned in the case that the
condition is true, and then a colon, and the
| | 07:33 | value that you want to be
assigned in case the condition is false.
| | 07:36 | So let's take a real example.
| | 07:37 | Suppose we had a couple of prices and
we wanted to find out which of price1 and
| | 07:42 | price2 was the low price.
| | 07:44 | Now we could write it like this:
| | 07:45 | we could say if price 1 < price2
then the lowPrice = price1; otherwise
| | 07:51 | lowPrice is price2.
| | 07:52 | Or we could write it like this:
| | 07:54 | we could say lowPrice = and then the condition.
| | 07:57 | The condition here is price1 < price2.
| | 08:01 | Now if that evaluates to true--we put the
question mark there--price1 would be the low price.
| | 08:06 | That's the true case. And then a colon
| | 08:09 | and then the value for the false case.
| | 08:10 | In this case, it will be price2.
| | 08:11 | So you can see we've taken the if statement
and compacted it down to just one line of code.
| | 08:17 | Finally, there is operator precedence.
| | 08:20 | Most programming languages have
the notion of operator precedence.
| | 08:23 | Operators are operated on in a
particular order, based upon what the operator is.
| | 08:28 | So let's take a look at an example.
| | 08:30 | Suppose I had this expression.
| | 08:32 | I have an integer variable named
result, and there's a whole bunch of numbers
| | 08:36 | being operated on, 2 + 3 * 6 / 2.
| | 08:40 | The temptation of course is to execute
this expression going from the left and
| | 08:43 | traveling to the right, just like
you probably learned in school.
| | 08:46 | And if you did that, you probably say,
okay, well 2 + 3 is 5 and then 5 * 6 is
| | 08:51 | 30 and then 30 / 2 is 15, so hey, the
answer must be 15, right? Well, wrong.
| | 08:56 | And the reason it's wrong is because
those operators are executed in order based
| | 09:01 | upon what the operator is.
| | 09:03 | This is what operator precedence means.
| | 09:05 | So that's actually wrong.
| | 09:07 | What happens is the multiplication
operator gets executed first, because that
| | 09:11 | comes first in the precedence order.
| | 09:14 | So 3 * 6 would be 18.
| | 09:16 | Then the division operator
would execute, and 18 * 2 would be 9.
| | 09:22 | Then we would go back and we would do
the addition, because 9 + 2 is now 11.
| | 09:27 | So the real result would be 11.
| | 09:29 | Now you can change the order of
precedence by using parentheses.
| | 09:33 | So if we put parentheses around the 2
and the 3 then things would execute in
| | 09:37 | the order that you thought they would.
| | 09:38 | In this case, the (2 + 3) would be
executed first because it's in parentheses.
| | 09:42 | Then *6 is 30, divided by 2 is 15,
| | 09:44 | so the answer in that case would be 15.
| | 09:47 | So how do you know which operators come first?
| | 09:49 | Well, let's take a look.
| | 09:50 | The operator precedence
operates in a very predictable order.
| | 09:53 | First, there is the
Multiplicative operators, which are things like
| | 09:57 | multiplication, division,
and the modulus operator.
| | 10:00 | Next comes the Additive operators,
which in this case are + and -.
| | 10:04 | Then there is the Comparison and Type
Testing, so things like >, <, >=, <=, the
| | 10:11 | is, the as operators.
| | 10:13 | Then the Equality tests come, so == and !=.
| | 10:17 | That's followed by a Conditional AND,
which is followed by Conditional OR.
| | 10:21 | Then the Ternary operator comes.
| | 10:23 | And then finally, the last operator
to execute is the Assignment operator.
| | 10:27 | Keep these rules in mind, because this is
the source of a lot of bugs in programs
| | 10:32 | of beginning developers.
| | 10:34 | And once you realize that the operators
execute in an order of precedence, this
| | 10:38 | will save you a lot of headaches down the road.
| | Collapse this transcript |
| Using constants and enumerations| 00:00 | In this example, we are going to look
at using constants and enumerations.
| | 00:04 | Constants and enumerations are
basically C# programming constructs that make
| | 00:09 | your code easier to
understand and easier to maintain.
| | 00:13 | So let's take a look at what we mean by that.
| | 00:16 | Suppose we had some code that looked like this.
| | 00:19 | So we have some if statement and we've
got some variable, and we are comparing it
| | 00:23 | to the constant number 32.
| | 00:26 | And if that condition evaluates to
true then some code is going to run.
| | 00:30 | The problem is this is a bad practice.
First of all, what does 32 even mean?
| | 00:33 | I mean if I am a
programmer, I am writing the code,
| | 00:35 | I might know what it means, but two years
from now, I might not know what it means.
| | 00:39 | Somebody goes to look at my code,
but has no idea what that means.
| | 00:42 | Worse yet, what if it changes in the future?
| | 00:44 | If I am using this 32 value all over my
program, I am going to have to change it
| | 00:48 | if for some reason in the future that
32 is no longer applicable and the test
| | 00:53 | needs to test for some other number.
| | 00:55 | Well, the way that we fix this problem
is by using constants and enumerations.
| | 01:00 | So we can write the same thing by writing
if (someVar == FREEZING), then the code runs.
| | 01:07 | That's much better.
| | 01:08 | It's clear what the code is trying to do.
| | 01:10 | It's testing for some
freezing value of some liquid.
| | 01:14 | And if we ever decide to switch it, we just
change the constant definition in one place.
| | 01:19 | And the way you define that constant
freezing is by using the const structure.
| | 01:24 | So here I am saying const and then the
int, and then the name of the constant
| | 01:29 | that I want to use is equal to some number.
| | 01:33 | So constants are used for numbers whose
value is not going to change over the
| | 01:38 | life of the program.
| | 01:40 | So here you can see I have got a
definition for const int FREEZING = 32.
| | 01:45 | That's the freezing point of water.
| | 01:47 | The freezing point of water is
very unlikely to change in the future,
| | 01:50 | so therefore, I define a constant for it.
| | 01:53 | So if I want to change this constant to
something else in the future, or change
| | 01:57 | it to some other definition, I just do
it in one place and the rest of my code
| | 02:01 | just picks up the change,
| | 02:03 | and people reading my code in
the future know what that means.
| | 02:06 | Enumerations are a close cousin to constants.
| | 02:09 | And what you'll probably find in many
situations is that you'll use a whole
| | 02:14 | bunch of constants that
are related to each other.
| | 02:16 | For example, if we had a constant for
the freezing point of water, we might have
| | 02:20 | a whole bunch of other
constants that go along with it.
| | 02:22 | There might be one for
LUKEWARM and for HOT and for BOILING.
| | 02:25 | Well, it seems kind of silly to have
all these separate constants defined for
| | 02:30 | different values that are really all related.
| | 02:32 | So the way you solve that problem is
using what's called an enumeration.
| | 02:37 | In this case, we can build what's
called an enumeration for temperatures, and
| | 02:41 | we just simply group them altogether.
| | 02:43 | So, for example, we would group the
value of FREEZING and LUKEWARM and HOT and
| | 02:48 | BOILING all into one enumeration.
| | 02:51 | This way if we wanted to add a new one
in the future--like say we want to add
| | 02:54 | one for ROOMTEMP--all we would do is
make room for it in the enumeration, add
| | 02:59 | the value for it, and then we are done.
| | 03:01 | So now we have a whole bunch of
temperatures that are grouped together logically,
| | 03:05 | instead of having a whole bunch
of different const int definitions.
| | 03:08 | Enumerations start off at 0 by
default if there is no value assignment.
| | 03:13 | So for example, if we have our
temperatures enumeration and we put something at
| | 03:17 | the front of it, like, say, REALLYCOLD,
that's going to default to the value of
| | 03:21 | 0, unless you explicitly assign a value to it.
| | 03:24 | So to build an enumeration, you simply
have the values that you want to assign
| | 03:28 | to words which are easy to read.
| | 03:30 | And if you don't assign it,
then it defaults to 0.
| | 03:34 | If you also don't make a definition
after one that's already been defined, then
| | 03:38 | that defaults to one more than
whatever the previous definition was.
| | 03:42 | So for example, if we were to put
another definition in here right after
| | 03:46 | FREEZING which would be, say,
JUSTBARELYABOVEFREEZING and we didn't put an
| | 03:50 | equal sign, then it would default
to the value of 33 in this case.
| | 03:54 | Now enumerations by default are
integer types, but you can specify other
| | 04:00 | types if you want to.
| | 04:01 | Now we'll learn a little bit more about
types in the next section, but just bear
| | 04:05 | with me here for a second.
| | 04:06 | So if we have temperatures and we
have all of these values assigned to our
| | 04:11 | temperature enumeration,
those default to integers.
| | 04:14 | But if I wanted to, say, assign them to
the value of a byte in order to save space
| | 04:18 | in my program for some reason, then I
could put a colon there and the name of
| | 04:22 | the type that I want the
temperature enumeration to be.
| | 04:25 | So for example, in this case, if I
know the value is never going to go above
| | 04:27 | 255, which is the maximum value that one byte
can hold, I can just define this to be a byte.
| | 04:34 | To define enumerations, you can use
types that are numeric in nature, such as
| | 04:38 | byte and shorts and ints and longs.
| | 04:41 | And again, we'll learn what these
are a little bit later in the course.
| | 04:44 | But I just wanted to point this out
here, that you can define enumerations
| | 04:48 | that are not integers by using a colon and
then the type that you want the enumeration to be.
| | 04:53 | So let's go ahead and jump over to
the code and see some constants and
| | 04:56 | enumerations in action.
| | 04:57 | Here I have got my ConstAndEnums
project open in my editor, and I've got
| | 05:03 | my Snippets.txt file.
| | 05:05 | And I've scrolled down to the
Constants and Enumerations section.
| | 05:08 | So let's go ahead and copy some
code over and see how things work.
| | 05:11 | So I am going to start with these lines
right here, copy those, and put them in
| | 05:17 | my program, right here in Main.
| | 05:20 | So I have now defined constants for
the freezing point of water and the
| | 05:24 | boiling point of water.
| | 05:25 | You can see I am getting a little
warning that says, hey, you've defined this
| | 05:28 | constant, but you've never used it,
so let's go ahead and fix that.
| | 05:31 | I am going to save, go back over to
my Snippets, and I am going to copy
| | 05:36 | this code right here.
| | 05:37 | So now I have copied in some code
that's going to use those constants.
| | 05:47 | So here, let's go down a little bit.
| | 05:49 | I've got an integer variable named
myTemp, and I am setting it to be 65.
| | 05:53 | And then I have an if else condition
for if myTemp is greater than freezing
| | 05:58 | point and it's less than the boiling
point, then we write out, hey, at this
| | 06:02 | temperature, water was liquid;
| | 06:04 | otherwise we write out, hey, water
is not liquid at this temperature.
| | 06:07 | So let's save and let's run it,
| | 06:11 | and we can see that at 65
degrees, water is a liquid.
| | 06:14 | And if we change this to, say,
30 and run it, then we say, aah!
| | 06:20 | At this temperature, water is not a liquid.
| | 06:24 | So let's do the same thing now, only
using an enumeration, because you can see
| | 06:27 | here, I've got two different
constants for freezing and boiling.
| | 06:30 | Let's go back to my Snippets.
| | 06:31 | What I am going to do is up here I
have an enumeration for my temperature,
| | 06:36 | so I am going to copy
that back over to my program.
| | 06:42 | Now I am going to put this
definition outside the Main function.
| | 06:45 | I am going to put it in my
class definition up here.
| | 06:48 | Paste that in, so now I have an
enumeration for my temperatures. So you can see
| | 06:51 | here that the syntax highlighting is
showing me that everything looks right.
| | 06:55 | So I have enumeration for FREEZING,
LUKEWARM, ROOMTEMP, HOT, and BOILING.
| | 06:59 | Go back to my snippets. And now I am going
to use these two lines down here instead.
| | 07:07 | Copy. And we'll go back to Main.
And what we'll do is we'll get rid of these
| | 07:14 | guys, and we'll paste these in.
| | 07:17 | So now you can see I am using
temperatures enumeration instead of the constants
| | 07:21 | that I've got defined here.
| | 07:22 | And in fact, since I am not using
them anymore, let's just get rid of them.
| | 07:25 | The nice thing about enumerations is
that, because they are part of your program
| | 07:29 | and the C# interpreter can look
at them and see what they are,
| | 07:32 | when you type, it will
actually help you type the value out.
| | 07:36 | So for example, suppose
this piece of code wasn't there.
| | 07:41 | I can start writing the word Temperatures,
| | 07:43 | and you can see that the Temperatures
IntelliSense is showing up right there.
| | 07:46 | So I am going to double-click
that and it's going to get inserted.
| | 07:48 | Then when I hit the period, you
can see that it's introspecting the
| | 07:52 | enumeration for me.
| | 07:53 | So I can scroll down to the one
that I want, and that's FREEZING.
| | 07:58 | So I am going to have to just do this.
Bear with me for a second while I do this,
| | 08:03 | because we'll learn about conversion
in the future, but I have to tell the
| | 08:07 | interpreter that the
Temperatures enumeration is an integer.
| | 08:11 | And now I can say okay, if the
temperature is greater than FREEZING and is less
| | 08:16 | than BOILING, then we are doing the same thing.
| | 08:18 | At this temperature, water
is a liquid or it's not.
| | 08:21 | So let's change this to 65 and run it,
| | 08:24 | and you can see that water is a liquid at 65.
| | 08:28 | The nice thing about this is that the
code here is much easier to read than
| | 08:31 | having some numerical value
that you don't know what it is.
| | 08:35 | And in the future, if I ever wanted to,
I could change these numbers up here,
| | 08:39 | and I would not have to change them all
over my program wherever they are being used.
| | 08:43 | Just make the change in one place.
| | 08:45 | So that's the argument for using
constants and enumerations to make your code a
| | 08:49 | lot easier to read and a lot easier to maintain.
| | Collapse this transcript |
| Using loops| 00:00 | Along with some pretty basic stuff,
like constants and enumerations and
| | 00:05 | conditional statements and operators
and expressions, loops are one of the most
| | 00:09 | basic building blocks of any
kind of programming language.
| | 00:13 | Loops are essentially blocks of
code that execute over and over again.
| | 00:18 | And there are two
different basic kinds of loops:
| | 00:22 | there are loops that execute while a
condition is met and there are loops that
| | 00:26 | execute a set number of times.
| | 00:29 | So for example, you might have a loop
that's running some piece of code for as
| | 00:33 | long as a certain condition is true,
like the user has not logged out, or the end
| | 00:38 | of a file has not yet been
reached, or something like that.
| | 00:41 | You might also have a loop that runs a
set number of times: the number of people
| | 00:45 | attending a concert or something like that.
| | 00:48 | The way that you write loops is by
using a couple of different constructs.
| | 00:52 | For loops that execute while a
condition is met, you have a while loop,
| | 00:57 | and the while loop is
written as you see it there.
| | 00:59 | It can have the keyword while.
| | 01:01 | And then inside some parentheses,
you have a condition that is true.
| | 01:05 | And then inside the curly braces,
you've got some code that's going to execute
| | 01:09 | as long as that condition is true.
| | 01:10 | There's also a close cousin of the
while loop, which is the do-while loop.
| | 01:15 | And in this case, the while goes at the
bottom of the loop instead of the top.
| | 01:20 | And the main difference here is that
the while loop is only going to execute
| | 01:25 | when that condition is met.
| | 01:27 | If that condition test is not met,
nothing inside the while loop is going to
| | 01:31 | run and that condition is evaluated before
the while loop ever even gets a chance to run.
| | 01:36 | The do-while loop is a little bit different.
| | 01:38 | The code that is inside that loop is
going to execute at least one time.
| | 01:43 | And that's because it executes once--
then the while is executed at the end of
| | 01:48 | the loop to see if things should keep going.
| | 01:51 | So in the case where you want to have a
loop that runs only while a condition is
| | 01:55 | met and no other times, use the while loop.
| | 01:57 | If you have a condition where you want
to execute some code just one time and
| | 02:02 | then check to see if you should
keep going, that's the do-while loop.
| | 02:05 | For the set number of times
case, there is the for loop.
| | 02:10 | And the for loop executes a given
number of times and it runs the code that's
| | 02:15 | inside the curly braces.
| | 02:16 | A close relative of the for
loop is the for-each loop,
| | 02:21 | but we're not going to cover that one in
this particular movie because it has to
| | 02:25 | do with something called enumeration.
| | 02:27 | And we'll look at it a
little bit later in the course.
| | 02:30 | For now we're going to concentrate
on the while, do-while, and for loops.
| | 02:35 | Let's take a look at the
code to see how this works.
| | 02:38 | I've got my example here opened.
| | 02:41 | This is my Loops project.
| | 02:43 | And over in my Snippets, I've got my code,
and I'm scrolled down to the Loops section.
| | 02:49 | So let's take a look at how
the basic while loop works.
| | 02:52 | So I am going to copy these lines of code here.
| | 02:54 | I am going to copy that,
and I'm going to paste into my Main.
| | 03:01 | So I've got here an integer variable
named myVal, and we have a basic while loop.
| | 03:07 | We're first going to write out a
string of text that says Basic while() loop.
| | 03:11 | And then you see here,
here's the while definition:
| | 03:14 | so while (myVal < 20). We're going to
write myVal is currently and we're going
| | 03:21 | to use the console's WriteLine method
with some string formatting here to write
| | 03:25 | out what the current value of myVal is.
| | 03:28 | As always with loops, you want to make
sure that the loop has some way to exit;
| | 03:32 | otherwise, you'll end up with
what's known as an infinite loop.
| | 03:36 | An infinite loop is a loop of code that
just keeps going and going and going and
| | 03:39 | going and never has any way to get out of it.
| | 03:42 | So you want to make sure that you've got some
code inside your loop, such that at some point
| | 03:47 | this condition up here is going to
become false, and therefore your loop can
| | 03:50 | terminate, and your program
can continue on its merry way.
| | 03:54 | So what we're doing here is, at the
bottom of this loop, we're taking myVal and
| | 03:59 | we're adding 3 to it each time.
| | 04:01 | And recall that the += notation
there means myVal = myVal + 3.
| | 04:07 | So when myVal becomes greater than 20,
that condition will no longer be true if
| | 04:11 | they're in the while loop,
and the loop should stop.
| | 04:13 | So let's save this, and we're
going to go ahead and run it.
| | 04:17 | And you can see that the string gets
written out, Basic while() loop, and myVal is
| | 04:23 | 15, and then we add 3, so myVal is currently 18.
| | 04:27 | And then we add 3 and myVal becomes 21.
| | 04:30 | So when the code executes and goes back
to the top of the loop, that test is no
| | 04:35 | longer true, and the loop stops.
| | 04:38 | So right here. So the code executes in
this line, from top to bottom. The last
| | 04:43 | statement is the myVal += 3 right here.
| | 04:46 | When that executes, it gets to this curly brace,
| | 04:49 | it will go back up to the top of the loop, and then
this condition gets tested, and it fails the test.
| | 04:54 | And that's what terminates the loop. Okay.
| | 04:56 | Let's take a look at another example.
| | 04:59 | In this case, we're going to look at
the do-while loop. And I am going to copy
| | 05:05 | these lines of code right here.
| | 05:07 | Okay, let's get rid of this one. And paste.
| | 05:19 | In this case, we have a do-while
loop, and remember that in the case of
| | 05:22 | the do-while loop, the code inside
the braces gets executed once before
| | 05:26 | this condition gets met.
| | 05:28 | So in this case we have
pretty much the same code.
| | 05:30 | We're writing out the
Console.WriteLine value there.
| | 05:33 | We're adding 3 each time.
| | 05:34 | But let's see what happens.
| | 05:36 | So this time we're going to
save, and we're going to run it.
| | 05:40 | You can see here that the do-while()
loop, myVal is currently 15, myVal is
| | 05:44 | currently 18, and then we add 3 and then
myVal is 21, and the condition no longer
| | 05:50 | is true and therefore the
loop executes right here.
| | 05:53 | So right here when we add the
myVal += 3. This is no longer running.
| | 05:57 | But let's watch what happens when
I set this up at 20 to begin with.
| | 06:02 | I am going to save it.
| | 06:03 | I am going to run it.
| | 06:05 | And you see even though
myVal is not less than 20,
| | 06:08 | it still goes through
the loop at least one time.
| | 06:12 | So that code is going to get executed
once before the while condition has a
| | 06:15 | chance to be evaluated.
| | 06:17 | So even though the condition is
false, the code got executed one time.
| | 06:22 | So that's the do-while loop.
| | 06:23 | Let's take a look at our friend, the for loop.
| | 06:25 | Here's the code for the for loop right here.
| | 06:31 | I am going to copy that,
and we're going to paste it.
| | 06:37 | A for loop is set up using three compact
statements within the for statement itself.
| | 06:43 | So here's the for right here.
| | 06:46 | And then the first statement is the
initialization of the counter variable.
| | 06:51 | In fact, I could expand that out and do
something like this, where I say int i,
| | 06:57 | and then I wouldn't need to do this here.
| | 06:59 | I would simply say for (i = 0).
| | 07:01 | What I was doing there was just
concatenating one with the other.
| | 07:05 | So this is the initialization,
or setup, of the counter variable.
| | 07:08 | Then we have the test to
see if i is less than myVal.
| | 07:12 | This is the condition that
gets evaluated each time.
| | 07:15 | And then this is the statement that gets
evaluated when the loop is complete. So this is setup,
| | 07:20 | this is the condition, and then this is
what happens each time through the loop.
| | 07:24 | So i is going to start out at 0.
| | 07:26 | We're going to test to see if it's less
than myVal, which is 20 right here, and
| | 07:30 | we're going to add 5 each time.
| | 07:32 | And each time through the loop
we're going to write out i is currently
| | 07:35 | whatever its value is.
| | 07:36 | So I am going to save and we run it.
| | 07:38 | And you can see that i starts out at 0,
then it's 5, then it's 10, then it's 15,
| | 07:44 | and then it gets to be 20, and that
condition no longer needs to be true.
| | 07:49 | So 20 is not less than 20.
| | 07:52 | If we change this to be less than or equal to,
then 20 will actually match the condition.
| | 07:57 | So if we run it again, you'll see that
in this case i is less than or equal to
| | 08:02 | myVal, because 20 matches the less
than or equal to part of the condition.
| | 08:08 | So that's the for loop, and that's how you get
a loop to execute a certain number of times.
| | 08:13 | Let's take a look at some other
keywords we can use with loops.
| | 08:15 | There are two special
keywords that can be used with loops.
| | 08:18 | There's the break keyword, which
breaks out of the loop at the current point,
| | 08:23 | regardless of whether the test
condition has been met or not.
| | 08:27 | And there's the continue keyword, which
basically says, hey, skip the rest of the
| | 08:32 | code in the loop and then just jump
back to the top of the loop code as if you
| | 08:37 | had it completed one of the loops.
| | 08:39 | So let's take a look at how these work.
| | 08:41 | So I am going to erase the code from
my previous example, and we're going to
| | 08:45 | go back to the Snippets, and I am
going to copy over the last part of the
| | 08:49 | example right here.
| | 08:50 | I am going to copy, and I am going to paste.
| | 08:56 | So in this case, we're going to
use the continue and break keywords.
| | 09:00 | So here I have a for loop that's
starting off at 0, and it's going to run until i
| | 09:06 | is less than 10, and we're
going to increment i by 1 each time.
| | 09:10 | We're using the postfix increment operator here.
| | 09:13 | Now, there are two special conditions in here.
| | 09:16 | When i is equal to 5, I am
going to use the continue keyword.
| | 09:21 | continue basically says, hey, skip
everything from here on down, go down to the
| | 09:25 | last brace, and then go back to the
top again and execute whatever the third
| | 09:29 | statement over here is--
| | 09:31 | this part of the increment loop right here.
| | 09:33 | And then in the case where i is equal
to 9, I am going to use the break keyword,
| | 09:38 | which basically means, hey, you know what?
| | 09:40 | Just stop the loop.
| | 09:41 | It doesn't really matter where we are.
| | 09:43 | It doesn't matter what the
condition test up here. Just stop.
| | 09:46 | So let's save and we will run it.
| | 09:49 | Let's take a look at the output.
| | 09:50 | So you can see that i starts off at 0,
Then it goes to 1, then 2, then 3, then 4.
| | 09:56 | But remember, for the 5 case,
we use the continue keyword.
| | 10:01 | So we skipped over the line of code that
said Console.WriteLine, so that line of
| | 10:05 | code never got executed.
| | 10:07 | The loop just continued as if it had
run, but it skipped passed all the logic
| | 10:11 | that put where the continue keyword was.
| | 10:14 | And then we continue incrementing,
so i is now 6, then 7, and then 8.
| | 10:19 | And then remember, when we got to the 9
case, we used the break keyword, which
| | 10:24 | stops the loop in its tracks,
as if the condition had failed.
| | 10:28 | So let's go back to the code,
and let's take this statement out.
| | 10:32 | I am going to comment this out and run it again.
| | 10:37 | And you can see, in this case, the loop
does make it to 9, and then the value of i
| | 10:41 | becomes 10, which is where it triggers
the condition, and the condition is no
| | 10:45 | longer met and the loop stops.
| | 10:47 | So if we go back to the code and we
uncomment this, put the code back in, if I
| | 10:52 | change this to say 7 and save and then
run, you'll see that in this case, the
| | 10:57 | loop only makes it as far as 6 because
as soon as i gets to be 7, we're calling
| | 11:02 | the break command, which stops the loop.
| | 11:05 | Loops are a very powerful part of
programming, and you can see that C# loops are
| | 11:10 | pretty versatile and pretty
powerful in their own right.
| | Collapse this transcript |
| Using functions and methods| 00:00 | The last major piece of program flow
that we're going to take a look at in this
| | 00:03 | section are functions.
| | 00:05 | Functions are a nice mechanism for
breaking up large sections of code into
| | 00:12 | smaller pieces that are reusable,
and make your programs easier to understand and
| | 00:17 | maintain. And one of the things
you'll find when you're doing your C#
| | 00:21 | development, or development in any
language, really, you'll find that any
| | 00:24 | nontrivial program that consists of
many lines of code starts to get really
| | 00:29 | unwieldy and is really hard to change
and maintain, and functions really make
| | 00:33 | that process a lot easier.
| | 00:35 | Now the reason why I included the
word "methods" is because C# is an
| | 00:40 | object-oriented language and in
object-oriented parlance, functions are
| | 00:44 | typically called methods, because in C#
a function has to be part of an object.
| | 00:50 | There are no global functions,
which I covered a little bit earlier.
| | 00:53 | So the word function and method are
pretty much interchangeable in this context.
| | 00:59 | So anywhere you see me use the word
functions, you can just mentally hear me
| | 01:03 | using the word methods, and/or vice versa.
| | 01:06 | To define a function, it's a
pretty straightforward process.
| | 01:11 | We start off by giving it a name.
| | 01:14 | So to create a function, the
function has to have a name, and you can use
| | 01:17 | whatever uppercase, lowercase rules you
want to use. In this case, I am starting
| | 01:20 | off with a lowercase letter and I am
using what's called CamelCase, and I am
| | 01:24 | capitalizing the interior words of the function.
| | 01:28 | But that's up to you.
| | 01:29 | You can use letters.
| | 01:30 | You can't use special symbols, like dollar
signs or parentheses or anything like that;
| | 01:34 | it's got to be alphanumeric.
| | 01:35 | So here I have a function
and I have given it a name.
| | 01:38 | Then I have to give it
what's called a parameter list.
| | 01:41 | There are two parentheses and inside
those parentheses, these are the arguments
| | 01:47 | that the function takes.
| | 01:49 | This is the data that the function
is going to operate on. And inside the
| | 01:53 | function, I have the code of the function.
| | 01:56 | This is the stuff that the function does.
| | 01:59 | In this case, the function is
simply calling Console.WriteLine.
| | 02:03 | In the parameter list, where the
arguments go, I can supply one or more arguments,
| | 02:09 | or parameters, to the function.
| | 02:11 | So for example, if I want to pass in
an integer, I would pass in int x. In
| | 02:16 | some other languages, like JavaScript,
you don't have to declare the type in
| | 02:20 | front of the argument.
| | 02:21 | You simply give the argument a name, and you pass
it into the function, and C# doesn't work like that.
| | 02:27 | In C# you have to tell the function, here's the
kind of argument that's going to be coming in.
| | 02:32 | In this case, it's an integer.
| | 02:34 | If I wanted to pass in more than one,
I would use a comma to separate them.
| | 02:38 | And in this case I am passing in an
integer named X and a date argument named D.
| | 02:44 | Now in addition to the name of the
function and the arguments, I have to say
| | 02:49 | what the return type of the function is.
What kind of value does the function pass back?
| | 02:55 | I can say, for example, that the
function passes back an integer.
| | 02:58 | Now, notice I don't name what
the function is passing back.
| | 03:01 | I am just simply saying here that
the function returns an integer. And it
| | 03:04 | can return an integer;
it can return a string;
| | 03:07 | it can return any other kind of data
type. And we'll learn a little bit more
| | 03:10 | about data types later on in the course.
| | 03:11 | But for now, just follow along with
me here. I am saying that this function
| | 03:15 | returns an integer, and it takes an
integer and a date as an argument.
| | 03:20 | If I didn't want to pass in any argument,
I can simply leave the area inside the
| | 03:24 | parentheses blank and not pass in any
arguments at all. But in this case, I've
| | 03:29 | got a couple of arguments.
| | 03:30 | And then finally, there is the code
inside the curly braces for the function, and
| | 03:34 | that's what the function actually does.
| | 03:36 | In cases where functions return a
value--in this case, this function is
| | 03:40 | returning an integer--
| | 03:41 | I have to make sure that the function
actually does that, and I do that by using
| | 03:44 | the return statement.
| | 03:46 | In this case, I am returning a
variable named someValue, which is probably
| | 03:52 | defined somewhere in
this function as an integer.
| | 03:55 | The value that I am returning has to match the
type of the return value for the function.
| | 04:01 | So if I declare this someValue variable
in my function somewhere, it would have
| | 04:05 | to be an integer just like
the return type of the function.
| | 04:08 | Functions don't have to return values.
| | 04:10 | I could just simply say void, in which
case I've defined a function that takes a
| | 04:14 | couple of arguments but doesn't return
anything. And in that case I don't need a
| | 04:19 | return statement at all.
| | 04:20 | I can just simply get rid of that, because
there is no return value for the function.
| | 04:25 | I can also just simply use the word
return with a semicolon by itself, but in
| | 04:29 | this case I've just got rid of it
because it doesn't return anything.
| | 04:32 | So let's actually jump over to the
code and see how to write a function that
| | 04:36 | does what we have described here.
| | 04:38 | So in my FuncsAndMethods project I've
also got my Snippets file open, and I have
| | 04:44 | scrolled down to the Functions and Methods part.
| | 04:46 | So let's go ahead and copy
some of this code and paste it in.
| | 04:49 | I am going to copy these three lines.
| | 04:52 | I will paste that, and let's
take a look at what I've pasted in.
| | 04:58 | I have got an integer variable
named result1, and then I am assigning
| | 05:02 | result1 the result of a formula
function. And you can see here there are some
| | 05:08 | red squiggles there.
| | 05:09 | It says, "The name 'formula' does
not exist in the current context."
| | 05:12 | That's a function that apparently takes an
integer argument which I have not defined yet.
| | 05:18 | So let me go get the code for the
formula function, and that's it right here.
| | 05:24 | I am going to copy that,
and I am going to paste it.
| | 05:30 | So now, I have defined a function named
formula which takes an integer argument
| | 05:35 | and returns an integer.
| | 05:36 | For the moment, you've probably noticed
this word static right here. Just bear
| | 05:40 | with me about why we need that.
| | 05:42 | I am not going to cover it right now.
| | 05:43 | We'll get to that when we get to the
section on object-oriented programming
| | 05:46 | a little bit later. It's just something
we need right now for the function to work.
| | 05:50 | So don't worry about that right
now. Let's pretend it's not there.
| | 05:53 | What's important is the return type
right here of int, and the argument it takes
| | 05:57 | is an int, and this is the
name of the function right here.
| | 06:01 | In some languages, for example C or
Objective-C, the order in which you define
| | 06:06 | your functions is somewhat important.
| | 06:08 | So for example, if this were C and I
put the definition of this function down
| | 06:13 | below where I am calling it up here,
| | 06:15 | I would have to have some type of
code statement up here that says, "Hey!
| | 06:20 | program, there is going to be this function
called formula that you're going to come across.
| | 06:23 | Don't worry about it."
| | 06:24 | I am just telling you about it now.
| | 06:26 | In C# you don't need to do that.
| | 06:28 | In C# you can just declare this
function wherever you like and you can call it
| | 06:31 | from over here, and the C# interpreter
is smart enough to realize oh, okay,
| | 06:35 | well, there must be a function named formula
coming down, so I will just wait till I see it.
| | 06:39 | So here's what we're going to do.
| | 06:40 | We're going to call the formula
function with an argument--in this case, it's
| | 06:44 | 14. The function is going to do its work.
| | 06:46 | It's going to return an integer value
and that value is going to be set into
| | 06:50 | result1, and then this statement right
here Console.WriteLine is going to write
| | 06:55 | out whatever the result is.
| | 06:56 | So let's go ahead and save that,
and let's run it. And you can see that the
| | 07:02 | result being written out is 24.
| | 07:05 | So the result of the formula
inside the function evaluated to be 24.
| | 07:10 | So I'll say, okay. Let's go back up here.
| | 07:12 | Let's change this to something else.
| | 07:13 | I am going to type a new variable, and I
am going to call it arg1. And I am going
| | 07:22 | to give it a value of 25. And now
instead of passing in the hard-coded value of
| | 07:32 | 14, I am going to copy arg1 and I am
going to paste it in the calling place
| | 07:38 | where I am calling formula.
| | 07:39 | I am going to save it, I am going to
run it, and you can see that now we've
| | 07:43 | produced a different result.
| | 07:45 | So that pretty much brings us
to the close of this section.
| | 07:48 | In this section we've
seen how program flow works.
| | 07:50 | We've covered things like functions,
and we've seen constants and enumerations.
| | 07:53 | We learned how to write conditional
statements, and we have learned about
| | 07:56 | operators and expressions.
| | 07:58 | We've got to the point now where we
continue on and learn more about C# and
| | 08:01 | learn how to do things like declare
variables and use objects and so on.
| | 08:05 | But this chapter should have given
you a good foundation for a lot of the
| | 08:08 | basic parts of C# that you're going
to come across in any program that you
| | 08:12 | decide to write, or work on.
| | Collapse this transcript |
|
|
4. VariablesUnderstanding data types| 00:00 | Earlier in one of the course, I
mentioned that C# was a strongly typed
| | 00:04 | language, meaning that you can't just
simply declare variables and not tell the
| | 00:10 | system what the types are.
| | 00:11 | You'll find that as you build your C#
programs, this actually becomes quite an
| | 00:15 | advantage, rather than the
encumbrance that it sounds like.
| | 00:19 | Program store and keep
track of all kinds of data.
| | 00:23 | They keep track of numbers and prices
and names and email addresses and dates,
| | 00:28 | and these pieces of data are stored in
memory locations called variables, and
| | 00:32 | each piece of data can have a type,
which is used to declare a variable.
| | 00:39 | In some languages, such as JavaScript,
you can declare variables and you can
| | 00:44 | change their types around.
| | 00:45 | You can do all kinds of great
stuff. And you can't do that with C#.
| | 00:50 | So for example, in
JavaScript you can just do this.
| | 00:52 | You can say myData = true;
that's okay in JavaScript.
| | 00:56 | You can't do that and C#; you have
to actually declare the variable.
| | 01:00 | In JavaScript if you just use a
variable about declaring it, JavaScript
| | 01:03 | assumes it's a global variable. Well, C# doesn't
have a global variables, so this wouldn't work.
| | 01:08 | You have to actually
declare it, so you declare it.
| | 01:11 | In JavaScript you can do
things like var myData = 123456.
| | 01:13 | And in fact, you can do this in to C# too.
| | 01:18 | C# does support the var keyword,
but it's a little bit advanced for C#, and we're
| | 01:23 | not going to cover it in this course.
| | 01:25 | However, in JavaScript you can do
things like this: once you declare the
| | 01:28 | variable and you've assigned it a number,
later on in life you can say, hey, you
| | 01:32 | know what, myData is a text string now.
| | 01:34 | Again, that's okay in JavaScript,
but you can't do that in C#.
| | 01:38 | Your variable can't change type
once you've declared it and once
| | 01:42 | you've initialized it.
| | 01:44 | So that's an example of things
that work in some other languages
| | 01:47 | that don't work in C#.
| | 01:49 | So how do you declare and name a variable in C#?
| | 01:52 | Well, let's take a look at that.
| | 01:53 | To declare variable, you simply indicate
a type and then you give it a name, and
| | 01:59 | optionally you can give the
variable an initial value.
| | 02:03 | So all of these are valid ways of declaring,
and in some cases initializing, C# variables.
| | 02:10 | C# variable names can start with a
letter or an underscore. And after that, you
| | 02:16 | can have letters, numbers,
and underscores up to 255 characters.
| | 02:22 | Now you can't start a
variable name with a number.
| | 02:25 | It has to be a letter or underscore,
and the letter can be upper- or lowercase.
| | 02:28 | Remember that C# is case sensitive.
| | 02:31 | So, uppercase and lowercase variable names are
different, so you have to keep that in mind.
| | 02:36 | This will sometimes lead to bugs for
newer C# developers who've come from
| | 02:40 | languages where things are not case sensitive.
| | 02:43 | They're case insensitive.
| | 02:44 | That's not the case here with C#.
| | 02:45 | You do have to remember that.
| | 02:46 | C# has a number of primitive data types
that are built into the language, and the
| | 02:53 | reason they're called primitive data
types is because they are the basic
| | 02:57 | building blocks that you
use to build other data types.
| | 03:00 | For example--and you've probably seen
me using some of these throughout the
| | 03:04 | course so far, as we built some of our examples--
| | 03:06 | there is the int data type, which is an integer.
| | 03:09 | That's 4 bytes. And it holds numbers from
about -2.1 billion up to about +2.1 billion.
| | 03:18 | There are date data types. The date is
8 bytes, and it represents January 1st
| | 03:24 | from the year one, up through midnight
on December 31st of the year 9999, which
| | 03:30 | is a very long time.
| | 03:31 | There's also a char data type, which is
a single character, and that's 2 bytes,
| | 03:35 | because it's Unicode.
| | 03:36 | Unlike other languages where
character is 1 byte, in C#, it's 2 bytes.
| | 03:40 | There are strings. Strings can hold
from about 0 to 2 billion characters.
| | 03:45 | That's a very, very long string.
| | 03:47 | There is also an object type. And in
this case the object is actually defined by
| | 03:52 | your program, although C# and .NET
does provide a base object definition for
| | 03:58 | you. And it takes up as much memory
as its structure and as memory allows.
| | 04:03 | So you can have all kinds of
data fields inside your objects.
| | 04:06 | And then rounding out the primitive
data types are a whole bunch of other types
| | 04:10 | like Boolean and bytes and decimals and
doubles, and all kinds of other numeric
| | 04:16 | data types and Boolean
other non numeric data types.
| | 04:19 | There is also a special kind of
data type in C# called a nullable type.
| | 04:24 | A nullable type can represent the full
range of values of the normal underlying
| | 04:29 | data type, along with the
additional value of null.
| | 04:35 | And normally when you declare a
variable, like an integer, it has to be a number;
| | 04:38 | you can't set that variable to
null like you can in JavaScript.
| | 04:42 | In C#, if you want to be able to do that, you
have to declare what's called a nullable type.
| | 04:47 | This is a little bit advanced, and we
won't see very much of it in the course,
| | 04:50 | but I wanted to point it out to you,
because you will occasionally run cross
| | 04:53 | it in your C# travels, so I wanted
make sure that you know what it is.
| | 04:57 | So, a nullable type, like I can said,
it can be null along with whatever its
| | 05:01 | normal data type is.
| | 05:02 | So for example, if we declared a
Boolean variable with the name of B, that can
| | 05:07 | be either true or false.
| | 05:09 | If you try to do this, however,
set it to null, that's an error.
| | 05:12 | You can't set B to null.
| | 05:13 | If you want to do that, you'll have
to declare the Boolean variable as a
| | 05:18 | nullable type, and the way you do that is
you declare as a bool with a question mark
| | 05:22 | at the end.
| | 05:23 | And that tells the compiler, hey, this is a
variable that can be either true or false or null.
| | 05:29 | You can do the same thing with integers.
| | 05:31 | If I put question mark on
the end of the integer,
| | 05:33 | it can be an integer
value or it can be null.
| | 05:37 | Using these kinds of primitive data
types, you can build all kinds of C#
| | 05:42 | variables and higher-order objects which
we will see a little bit later in the course.
| | 05:46 | For now though, now that we've seen
primitive data types, there is one other
| | 05:49 | thing we just need to look at and
understand, and that is how C# deals with
| | 05:52 | the notion of objects.
| | Collapse this transcript |
| (Almost) everything is an object| 00:00 | One of the things that I said earlier
on in one of the course is that almost
| | 00:02 | everything is an object in .NET and in
C#. And the way that that works is that
| | 00:08 | at the base level of the .NET library
is a base type called System.Object.
| | 00:14 | All of the other types that we talked
about so far, such as ints and doubles and
| | 00:18 | characters and bytes and so on, all
of these are primitive types, but C#
| | 00:22 | actually derives all of these base
primitive types from System.Object.
| | 00:28 | What's interesting about this is that
even though the int data type is built
| | 00:32 | into .NET and C#, int actually maps to
a System.Int32. int is just a shorthand
| | 00:40 | way of saying, use the class
System.Int32. The same thing goes for char.
| | 00:45 | A char data type is
actually a System.Char object.
| | 00:49 | Same thing with strings;
strings are System.String objects.
| | 00:52 | These all derive from System.Object,
and the same is true for all the other
| | 00:56 | objects that you see listed here,
and all the primitive data types.
| | 00:58 | Date, bytes, doubles, all of
those are actually objects.
| | 01:02 | They derive from System.Object.
| | 01:04 | So why is this important?
| | 01:05 | Well, it lets you do some pretty neat things.
| | 01:07 | If I were to declare a variable int i = 0,
| | 01:11 | I could do the same thing
by saying int i = new int.
| | 01:15 | Other languages don't let you do this
because they don't understand it, but in
| | 01:18 | C# and .NET, because pretty much
everything is an object, you can do this.
| | 01:22 | These are functionally equivalent to
each other. Declaring the variable as an
| | 01:26 | integer, initializing it to 0,
and saying new is pretty much the same thing.
| | 01:32 | It also means that the built-in
objects have some pretty cool features.
| | 01:36 | So for example, this integer is
really an object, and it has functions that
| | 01:40 | I can call on it. So I can do things like
i.GetType, and that will return System.In32.
| | 01:46 | That's the kind of object that it is.
| | 01:48 | I could say, i.ToString,
and that would return a string.
| | 01:51 | Now remember, I'm doing
all this on a basic integer.
| | 01:53 | I can do things like i.Equals, and give
it an argument, and that returns whether
| | 01:58 | two objects are equal.
| | 01:59 | So once you get around the idea that
everything pretty much in .NET and C# is an object,
| | 02:05 | it gives you a certain amount of
freedom in your programs and some really great
| | 02:09 | functionality that other
languages don't provide.
| | 02:11 | Let's take a look at an example.
| | 02:13 | Let's return to our old friend, the is operator.
| | 02:16 | Now I briefly talked about the is
operator earlier on in the course, but now
| | 02:20 | let's take a look at how you might use it.
| | 02:21 | Suppose I had a function that took an
object as an argument. And again, remember
| | 02:27 | here that that word "object" is really an alias.
| | 02:30 | It is a shorthand way of saying System.Object.
| | 02:33 | So here I have a function that's taking
an object as an argument and it returns
| | 02:37 | an integer data type.
| | 02:39 | Inside this function I would be able
to do things like say, hey, if the obj
| | 02:43 | argument that I'm being given is an int,
and then I can convert that object to
| | 02:48 | an integer and then operate on the
argument as if it were an integer. Or I could
| | 02:52 | say, hey, if the obj is a string, then
convert the object to a string and then
| | 02:57 | operate on it as if it were a string.
| | 02:59 | This gives me a lot of
flexibility in the way that I write my code.
| | 03:02 | I can write some C# code that's very flexible,
| | 03:04 | takes different kinds of arguments
in one large container, and then convert
| | 03:09 | between them as I need them.
| | 03:11 | So what's so great about this?
| | 03:12 | Well, first, the fact that pretty
much everything is an object provides a
| | 03:16 | unified way of working with all
the variable types. You don't have to
| | 03:21 | treat primitive types one way and objects
another way like you do in other languages.
| | 03:26 | Basic variable types in C# have some
pretty cool automatic features built in,
| | 03:31 | and we'll see more of this as we work with
each one of the other data types in depth.
| | 03:35 | All the C# types can be converted to
and from objects, so they can be passed to
| | 03:40 | functions that take objects as
parameters, as you saw it earlier.
| | 03:44 | So now you can write code that's very flexible.
| | 03:46 | You can write functions that take
objects and take variables of different types
| | 03:50 | and work on them as if they
were each with their own types.
| | 03:54 | So for example, I can write a
function that takes an object or a series of
| | 03:57 | objects, pass them all kinds of variables,
like strings and integers and doubles
| | 04:01 | and floats, find out what kinds they
are, and then work on them as I would in
| | 04:05 | ordinary variable of that type.
| | 04:07 | And will see examples of this
as we move through the course.
| | Collapse this transcript |
| Working with numbers| 00:00 | Let's talk a little bit about
working with integer numbers in C#.
| | 00:03 | Up until now you've been seeing me
use the int data type throughout all the
| | 00:07 | examples that we've encountered up
until now, but there are plenty of other
| | 00:10 | ways of working with integer numbers.
And the only real difference between the
| | 00:14 | various data types for working with
integers is the size of the variable
| | 00:19 | container, which basically dictates the
range of numbers that that variable can hold.
| | 00:23 | For example, there is bytes, which are 8
bits in size, and they are unsigned by default.
| | 00:31 | They are 0 to 255.
| | 00:34 | That's just 8 bits, and 255 is the largest
number that you can hold inside of a byte.
| | 00:40 | Along with a byte is the sbyte, which
means signed byte, that's also 8 bits, and
| | 00:46 | it can hold the number from -128 to 127.
| | 00:51 | So byte and sbyte are both the same size.
| | 00:53 | It's just a question of which one you
want to use when you know that the number
| | 00:56 | is only going to be positive, or
if the number might be signed.
| | 00:59 | Similarly, there is a data type called
the short. The short is 16 bits, or 2 bytes,
| | 01:04 | and that can hold -32,768 up to 32,767.
| | 01:10 | Now notice unlike byte,
shorts are signed by default.
| | 01:14 | So if you want to use an unsigned
version of this, you have to use the ushort,
| | 01:18 | which stands for unsigned short.
It's also 16 bits, and it can hold the
| | 01:22 | number from 0 to 65,535.
| | 01:24 | The next step off from there is of
course the int, which is what you've been
| | 01:29 | seeing we use all this time.
| | 01:30 | It's 32 bits, and it can hold from -2.1
billion to 2.1 billion. And there is of
| | 01:36 | course an unsigned version of it, which
is uint, for unsigned integer. It's also
| | 01:40 | 32 bits, and since it's unsigned, it
can hold from 0 up to about 4.3 billion.
| | 01:48 | That's a pretty good range of data,
but suppose we want to handle numbers that
| | 01:52 | are larger than 4.3 billion.
| | 01:54 | Well, no, we are not out of luck.
| | 01:55 | There are other data types that we can use.
| | 01:58 | There is of course the long, which is 64
bits, and it has a range of well really,
| | 02:04 | really, really, really big.
| | 02:06 | You can see those numbers right there.
| | 02:08 | It goes from that -9 up to the
9, whatever that number even is.
| | 02:11 | I have no idea what the name of that
number is, but it's really, really huge.
| | 02:15 | In addition to the long, there is the
unsigned version of this, which is the ulong.
| | 02:21 | It's also 64 bits, and it can handle
from 0 to well, even really, really bigger.
| | 02:27 | But of course there's also floating
point numbers, not just integers. Usually we
| | 02:31 | use floating-point numbers for
things like decimals and other kinds of
| | 02:35 | fractional numbers. And to do that
there is a float number type and when you
| | 02:39 | declare a float number, you have to
put a lowercase f on the end. And you can
| | 02:43 | see here I am declaring a floating
point number of 123.45, and it has 7 digits
| | 02:48 | of precision from the
range that I have shown there.
| | 02:50 | There is also a double, which is
another type of floating-point number, but it
| | 02:55 | has 15 to 16 digits of precision.
And you can see that when you declare it you
| | 02:59 | have to put a little d on the end to
distinguish it from the float. Floats have
| | 03:02 | fs; doubles have d. So in this case
I've got a double number which has much
| | 03:08 | higher precision than the floating-point.
| | 03:10 | And then finally there's the decimal number.
| | 03:13 | The decimal number is an interesting
beast because it actually works in base 10
| | 03:18 | and not base 2, like the other kinds of
floating-point number types that C# works with.
| | 03:24 | And to declare a decimal number, you
simply say decimal and then the name of the
| | 03:27 | variable. And here I've got 123.45,
and you put the little lowercase m on the end
| | 03:33 | which indicates that it is a decimal number.
| | 03:35 | Decimal numbers have 28 to 29 digits
of precision, making them very, very
| | 03:40 | highly accurate numbers.
| | 03:42 | In addition to these data types, there are
some special floating-point values that
| | 03:47 | you should be aware of.
| | 03:48 | The first of these is NaN, which
means Not a Number. If a floating-point
| | 03:53 | variable gets into a state where you
either try to divide by 0, or some other
| | 03:56 | kind of error happens, then the variable
is set to NaN which means not a number.
| | 04:02 | There is also a PositiveInfinity
and a NegativeInfinity setting.
| | 04:06 | For example, if you have a variable f
defined to be of type float, you can do
| | 04:11 | things like say, hey, if f is less
than float.PositiveInfinity. You can also
| | 04:16 | check to see if float is equal to not a number.
| | 04:19 | You can do things like float is
PositiveInfinity, or is NegativeInfinity, and
| | 04:24 | these are useful for
things like sorting algorithms.
| | 04:26 | You can also check to see if the
float is not a number. Again because these
| | 04:30 | floating-point data types, along with
all the other primitive data types, derive
| | 04:33 | from System.Object they have all these great
methods and properties built into the language.
| | 04:39 | Okay, let's talk a little about why
you'd use floating points, such as floats or
| | 04:44 | doubles, versus something like decimal,
because one of the things you will find
| | 04:47 | is that with floating point numbers--
and I am not going to go too deep into
| | 04:51 | this because it's a bit of a advanced
subject--but because of the way computers
| | 04:54 | work, computers calculate values using base 2
notation rather than base 10 like we humans do,
| | 05:01 | and that can lead to a loss of
precision for certain kinds of transactions.
| | 05:06 | So let's take a look at a piece of
code that explains how that happens.
| | 05:10 | So I have got my DoubleVsDecimal
project open here, and here's the program file,
| | 05:16 | and I've got my snippets open as well.
| | 05:18 | So what I am going to do is copy these
lines of code over to my main function.
| | 05:25 | So what we are going to do in this
example is compare how double precision works
| | 05:30 | with decimal precision. And like I said
earlier, internally, computers represent
| | 05:35 | numbers having to do with base 2 notation.
| | 05:39 | This is the famed 0s and 1s you've
probably heard about if you've ever worked
| | 05:43 | with software before.
| | 05:44 | But what it essentially means is that
because of the way numbers are calculated
| | 05:47 | on a microprocessor, you can sometimes
lose precision when working with certain
| | 05:51 | data types. And I am going to show you a
difference of how decimals are handled
| | 05:56 | versus how doubles are handled.
| | 05:58 | So right here at the top of my function
I have got two variables, twentieth and
| | 06:02 | one. And you can see that I defined
twentieth and one to be types double and
| | 06:07 | so I have got 0.2f and 1.0f. And what I am
going to do is write out what one - twentieth is.
| | 06:16 | So 1.0 - 0.2, you would expect
that to be equal to 0.8, right?
| | 06:21 | So let's see how the double data type and
decimal data type compare when doing the
| | 06:26 | same kind of option, because down here,
I have got two variables, decimals, which
| | 06:30 | are one twentieth and the real one.
| | 06:33 | So now I have got the same kind of calculation.
| | 06:35 | I have got 1.0, subtracting
tracking off 0.2 each time.
| | 06:38 | The only thing that's different is
in one case they are doubles; in one
| | 06:41 | case they are decimals.
| | 06:43 | So let's save this, and let's run it.
And you can see that in the first case the
| | 06:48 | 1.0 - 0.2 when using a double results
in 0.799999...whatever, a whole bunch of,
| | 06:56 | like, you know high-precision numbers
here. But obviously there is a loss of
| | 07:01 | precision when using a double number,
whereas in the case of the decimal the 1.0
| | 07:07 | - 0.2 did fact result in
0.8, as you would expect.
| | 07:13 | And again, that's because the decimal
data type works with base 10 numbers
| | 07:17 | naturally, whereas doubles
work with base 2 numbers.
| | 07:20 | Now you might be saying to yourself, oh my God!
| | 07:22 | Is this some kind of a bug in .NET?
| | 07:23 | Is this a huge shortcoming of C#? It's not.
| | 07:26 | You will find this in lots of
different computer languages that work with
| | 07:29 | floating-point numbers. Whether it's C or
Objective-C or Java, it doesn't really matter.
| | 07:33 | This is just one of the ways that
computers keep track of numbers internally.
| | 07:37 | So let's go back and take a look at
the chart of when you want to use double
| | 07:39 | versus when you want to use decimal.
| | 07:41 | Let's take a look at why double and
decimal are different from each other.
| | 07:44 | First, in the nature of precision,
doubles are 15 to 16 figures of precision,
| | 07:49 | where decimals are 28 to 29 figures,
so you've got double the amount of
| | 07:52 | precision in a decimal
number as you do a double.
| | 07:55 | In internal format, in other words
how the microprocessor on the computer
| | 07:58 | works with the number, in doubles
it's base 2; in decimals it's base 10.
| | 08:04 | So, so far it's looking like you might
never want to use a double, right?
| | 08:07 | After all you've got
higher precision using base 10.
| | 08:10 | Speed, however, is a
important factor to consider.
| | 08:13 | Because doubles are native to the CPU--
in other words they are native in the
| | 08:17 | fact that they use base 2 notation--the speed
when using doubles is very, very, very fast.
| | 08:22 | Decimals, on the other hand, because
they work in base 10 and have to be
| | 08:26 | conferred to and from the native
processor format, can be up to 10 times slower
| | 08:30 | than using doubles.
| | 08:32 | So what are they good for?
| | 08:33 | Well, scientific calculations can
usually be executed quite accurately and quite
| | 08:37 | fast using doubles, so they're good for
scientific calculations, whereas decimal
| | 08:42 | numbers are good for financial calculations.
| | 08:45 | When you're dealing with hundreds of
millions or billions of dollars, or even
| | 08:48 | small amounts but many, many, many
times, these differences in precision and
| | 08:52 | accuracy on the CPU can add up to real money.
| | 08:56 | So because decimals work in base
10 and are very highly accurate when
| | 08:59 | working with floating-point
numbers, they are ideal for being used in
| | 09:03 | financial calculations.
| | 09:05 | You can use doubles and
other floating-point numbers for
| | 09:07 | scientific calculations.
| | Collapse this transcript |
| Working with characters and strings| 00:00 | C# also has built-in data types for
working with characters and strings.
| | 00:05 | They're the char and string
data types, not surprisingly.
| | 00:08 | The character data type, or char, in C#
represents a single Unicode character, and
| | 00:13 | that's 16 bits or 2 bytes.
| | 00:15 | So the way we declare is char
| | 00:18 | and then the name that you want to give the
variable, and you can initialize if you want to.
| | 00:23 | And it's important in C# to recognize
that, unlike languages like JavaScript,
| | 00:26 | when you declare characters you have
to use a single quotes, and for strings
| | 00:31 | you use double quotes. And in
JavaScript you can use either single or double
| | 00:35 | quotes for the characters or full strings,
| | 00:36 | it doesn't matter; in C# it does matter.
| | 00:39 | So, for the character data type use
single quotes; for strings use double quotes.
| | 00:42 | If you're not familiar with
Unicode, don't worry too much about it.
| | 00:45 | It's basically an international
standard for representing a wide variety of
| | 00:49 | characters from a wide variety of
languages, and it supersedes the old ASCII
| | 00:53 | data set that were used in
computers up until just recently.
| | 00:57 | So here we have an example of a
character being declared, and this is a
| | 00:59 | lowercase letter a. And as I mentioned
it's 16 bits, or 2 bytes, but you are not
| | 01:04 | limited to lowercase letters.
| | 01:05 | You can use things like numbers.
| | 01:07 | You can even use punctuation.
All of these are legitimate characters.
| | 01:11 | For strings, you use the string
data type, and a string is a series of
| | 01:17 | Unicode characters.
| | 01:18 | And unlike other languages, like,
say, C or languages based on it, like
| | 01:22 | Objective-C, C# provides a native
built-in data type for working with strings
| | 01:28 | and it's just called the string.
| | 01:29 | So to declare a string, you use the
string data type, again the name of the
| | 01:33 | variable that you want, and you can
initialize it, and you can see I'm using
| | 01:36 | double quotes to initialize my string,
which is part of the C# syntax rules.
| | 01:42 | strings can also have escape characters
in them. In this case, for example, \n
| | 01:47 | represents a new line character,
and these are handled automatically for you by C#.
| | 01:52 | If you make a string that has an escape
sequence, which is basically a backslash
| | 01:56 | followed by a special character code,
such as a T for tab or an R for a
| | 02:01 | carriage return or N for a new line,
C# will simply convert that for you.
| | 02:05 | Now this provides some rather
interesting side effects for working with things
| | 02:09 | like directory paths.
| | 02:10 | So for example, if I wanted to make a
string that contained a directory path,
| | 02:15 | I'd have to escape out the backslashes
by putting a backslash in front of them.
| | 02:20 | And this can get a little
cumbersome and tiresome to read,
| | 02:23 | so C# provides a special way for
telling the compiler, hey, don't worry
| | 02:28 | about escape characters.
| | 02:29 | I just want every character that's
in the string to be what it really is.
| | 02:32 | And the way you do that is you put an
@ symbol in the front of the string.
| | 02:36 | So in the case of declaring the
myDirectory variable, in the first case I had
| | 02:40 | to escape out the backslashes; in the
second case, by putting that little @
| | 02:43 | symbol in front of the string, I'm
telling the compiler, hey, those backslashes
| | 02:46 | aren't escape characters;
| | 02:47 | they are just real backslashes--
please treat them as such.
| | 02:50 | But the fun doesn't stop there.
| | 02:52 | Remember that characters
and strings are objects.
| | 02:55 | The character data type is really a
system.char object, and the string data type
| | 03:00 | is really a system.string object,
which basically means that each one of these
| | 03:05 | data types has some really cool
features and methods built in.
| | 03:09 | So for example, if I define a
character variable as the lowercase letter a
| | 03:13 | right here, I can do some
really cool things on it.
| | 03:15 | I can ask the character, hey, is it an
uppercase letter, or it is it a digit, or
| | 03:20 | is it a letter? Is it
punctuation or a white space?
| | 03:24 | I can do things like convert the
character to uppercase or to lowercase.
| | 03:29 | The same is true of things like strings.
| | 03:31 | If I declare a variable that
holds a string, I can do some really
| | 03:35 | interesting things on it, because
remember, it's an object, and the objects
| | 03:38 | have built-in methods.
| | 03:39 | So for example, I can do things like
convert the string to upper- or lowercase.
| | 03:44 | I can search the string to see
where a substring appears in the string.
| | 03:49 | I can do that searching
forward or searching backwards.
| | 03:52 | I can take strings and
trim white space off of them.
| | 03:55 | We already saw how to do
things like string.formatting using
| | 03:57 | the Console.WriteLine.
| | 03:59 | You can see if a string is null or is empty.
And all of these features come built in
| | 04:06 | to the language, simply because these
data types, even though they're primitives,
| | 04:10 | derive from System.Object.
| | 04:12 | One of the things to keep in mind is
that strings are what's called immutable.
| | 04:17 | They can't be changed once they are created.
| | 04:20 | Now you might be saying, well, wait a second Joe.
| | 04:21 | I've seen you change strings throughout
this course so far. What you're talking about?
| | 04:25 | Well, the thing is that operations
that appear to change a string actually
| | 04:29 | create a new string, and the thing
is, this can cause a pretty significant
| | 04:34 | performance penalty if you're not careful.
| | 04:37 | So let's take an example. Suppose we
had a string variable called Result and we
| | 04:42 | initialize it to be an empty string,
and then we have a loop that executes, say, a
| | 04:46 | thousand times, and then inside that
loop we're saying, result += "some other
| | 04:49 | strings", you know some kind
of thing that we calculated.
| | 04:54 | Well, even though that += appears to
be modifying the string, what's really
| | 05:00 | happening is, each time this loop
executes, a new string is being created that
| | 05:06 | holds the temporary results of
concatenating the string on the end, and then
| | 05:10 | that new string is assigned to the
result variable, and then the old string that
| | 05:16 | used to be there is just simply discarded.
| | 05:18 | Now, if you do this a lot in your
programs, you're going to hit a pretty
| | 05:22 | significant performance penalty.
| | 05:23 | So if you're doing a whole a lot of
string manipulation, sometimes it's better
| | 05:27 | to use some of the built-in classes to do this.
| | 05:29 | C# provides one of these called the
stringBuilder. So what you do is you would
| | 05:33 | instead of just declaring
a variable named result,
| | 05:36 | you'd build a stringBuilder object.
| | 05:39 | In this case, I'm using the
stringBuilder class to declare a variable called sb.
| | 05:43 | And then instead of doing a
concatenation in the loop, like you see there, I'll
| | 05:46 | simply use the stringBuilder's Append
method. And we will cover objects such
| | 05:50 | as this later on, but the point here is that
I'm not just using a straight string to do this.
| | 05:55 | At the end, if I wanted to get the whole
result of the stringBuilder as one long
| | 05:59 | string, I'd simply call the Tostring
method on it and assign it to a string
| | 06:03 | variable that called result.
| | 06:05 | Let's take a look at some examples of
using some of the features that we've seen
| | 06:08 | here for characters and strings in real code.
| | 06:10 | So I'm over here in my code, and I've
got my charsAndstrings project open, and
| | 06:16 | I've also got my ExamplesSnippets open.
Over here in the ExampleSnippets, you
| | 06:21 | can see that I've scrolled down
to the chars and strings sections.
| | 06:25 | So let's go ahead and copy some of
this, so I'm going to copy these lines
| | 06:27 | right here. Paste those in. So I'm going to
save, and don't worry about the little warning.
| | 06:36 | I am not using the string.
| | 06:37 | We'll get to that in a second.
| | 06:39 | So you can see here that I've declared a
variable called mychar, which is a char
| | 06:43 | type, and it's a lowercase letter a.
And essentially what I'm doing is
| | 06:47 | exercising some of the methods that
the character class provides for me.
| | 06:50 | So I'm going to do a whole bunch of
WriteLines and write out the results of a
| | 06:55 | whole bunch of these methods, things
like IsUpper, IsDigit, and so on.
| | 06:58 | So it starts off as the lowercase letter
a. So let's go ahead and run the code
| | 07:03 | and see what happens.
| | 07:05 | So you can see that the results for
these tests are, well, is lowercase letter
| | 07:10 | a upper? No, that's false.
| | 07:11 | It's obviously not a digit. It is a letter.
| | 07:14 | It's not white space or punctuation.
And you can see here the results of calling
| | 07:18 | ToUpper and ToLower on it.
| | 07:20 | Okay, so let's change it.
| | 07:23 | Let's change it to say the number 8,
and we will save and we will rerun it.
| | 07:27 | Well, in this case you can see that
ToUpper and ToLower have the same result,
| | 07:32 | because there is no such thing as an
upper- and lowercase 8, but in this case the
| | 07:35 | IsDigit function returned as true.
| | 07:37 | And I'll leave this as an
exercise for you to play with.
| | 07:40 | What I'm going to now, though,
is go back to the Snippets.
| | 07:41 | I'm going to copy those string tests.
| | 07:48 | Let's just do some of the string tests.
| | 07:54 | So in this case you can see
I've got my string variable.
| | 07:57 | It says, "This is a message with a new line,"
and you can see it's got some leading
| | 08:00 | and trailing spaces on the front and
back. And we are going to do things like
| | 08:04 | call Trim and ToUpper and
ToLower and IndexOf and LastIndexOf.
| | 08:09 | So let's go ahead and save this and run
it. And you can see here that this is a
| | 08:17 | string with a message and
new line and spaces in it.
| | 08:19 | You can see that the spaces have been
cut off. Here the result of ToUpper is
| | 08:24 | that all the letters have
been converted to uppercase.
| | 08:27 | Here they've all been converted to
lowercase, and then we found the indexes of
| | 08:31 | the letter a and the substring end.
| | 08:32 | So you can see that even though we've
got primitive data types for characters
| | 08:36 | and strings, they're really pretty
powerful, just again, because they derive
| | 08:40 | from the base System.Object class in C#.
And because they are objects, they have
| | 08:45 | a whole bunch of really useful
features that just come built in.
| | Collapse this transcript |
| Understanding variable scope| 00:00 | One of the other common "gotchas" that you
have to watch out for when you're using
| | 00:04 | languages like C# or Objective-C or
Java or anything else that's a compiled
| | 00:08 | language is the notion of variable scope.
| | 00:11 | All variables have what's called a scope.
| | 00:13 | This is where the variable is
visible to the code and can be used.
| | 00:18 | So let's take a look at an
example, and then I'll explain it.
| | 00:21 | So suppose I had a function named
myFunction and inside that function I had a
| | 00:25 | variable called X, and I've declared the
variable X and I've assigned it a value of 10.
| | 00:29 | And suppose I also have a for loop and
inside the for loop I've got a variable
| | 00:34 | named Y which I'm declaring inside the
for loop and the value of Y is being set
| | 00:38 | to the value of X+20.
| | 00:41 | That's okay because I can refer to
the value of X inside the for loop.
| | 00:44 | I can declare the Y variable
inside the for loop as well.
| | 00:48 | Now I can also refer to the X variable
here if I wanted to use the increment
| | 00:53 | operator on X outside the for loop;
that's fine. And I can also increment X
| | 00:59 | outside the for loop after
the for loop; that's fine too.
| | 01:02 | What I can't do, however, is refer to the
Y variable outside of the for loop. Why?
| | 01:08 | Because it's not available there.
| | 01:09 | I've declared it inside the for loop.
And in this case when you declare
| | 01:14 | the variable inside those curly
braces, that variable is only valid inside
| | 01:20 | those curly braces.
| | 01:21 | That's because in languages like C#
variables have what's called a block scope.
| | 01:28 | Those curly braces define a block of
code the same way that the curly braces
| | 01:33 | near the function define a block of code.
| | 01:35 | This is not the case in a language like
JavaScript, and the reason is because in
| | 01:40 | languages like JavaScript
variables have function-level scope.
| | 01:45 | When the JavaScript interpreter goes to
interpret the function, it first looks
| | 01:49 | through the function to find variable
declarations, and then it lifts them to
| | 01:54 | the top of the function.
| | 01:56 | It does that internally;
| | 01:57 | it doesn't modify your script code.
| | 01:58 | But it gives all the variables inside
the function the same function-level scope.
| | 02:03 | That is not true in a language like C#.
| | 02:07 | In a language like C# or language
like C or Objective-C or Java, the variable
| | 02:12 | is only available to you in
the block where it is declared.
| | 02:16 | So let's take a look at this in
action, and we can see how it works.
| | 02:21 | Over here in the code I've got my
VariableScope project open, and here in the
| | 02:24 | Snippets I've scrolled down to the
Variable Scope. And I'm going to copy these lines.
| | 02:29 | I'm going to paste it in right here.
| | 02:32 | So here I have my loop, and you can
see inside the loop I'm declaring a
| | 02:38 | variable named int var1.
| | 02:41 | So when I run this program--let's just write it
really click--you can see that what's
| | 02:44 | going to happen is I'm going to
WriteLine, the value of var1 at pass whatever I
| | 02:49 | is is whatever the value of var1 is.
| | 02:51 | So I'm going to run it, and you can see
that it's staying the value of 20 all the
| | 02:55 | way through the loop.
| | 02:56 | So now let's take a look at what happens
when I try to uncomment this line of code here.
| | 03:00 | I'm going to try to WriteLine the last
value of var1, but I'm going to do it
| | 03:05 | outside the for loop.
| | 03:07 | I am going to save, and you can see
that I'm getting a little red
| | 03:11 | squiggle there which basically says,
hey, the name var1 does not exist in
| | 03:15 | the current context.
| | 03:16 | That's because it's
declared inside this for loop.
| | 03:19 | So if I wanted to do this, I would have
to cut that and move it up here and save,
| | 03:25 | and now everything works fine.
| | 03:27 | So let's go ahead and undo
that. Put it back where it was.
| | 03:30 | You might be wondering, hey, you
know, in other languages I can re-declare
| | 03:35 | variables in different scopes and
they're just given different meanings.
| | 03:38 | So for example, the C and Objective-C
languages let you do something like this.
| | 03:47 | And what I've done here is I've
declared the variable var1 in a separate scope
| | 03:51 | than the other var1 that's inside the for scope.
| | 03:55 | Inside the for loop you'd think that
this variable would have its own scope and
| | 03:59 | this will have a different one,
but that's not the way C# works.
| | 04:03 | This can be very confusing to someone
who's reading code, and it's also the
| | 04:07 | source of a lot of bugs in other languages.
| | 04:10 | So the designers of C# explicitly
don't allow variables to be declared in
| | 04:15 | separate scopes with the same name.
| | 04:17 | You can see that when I try to do this
there is a little squiggle down here
| | 04:20 | that says, hey, a local variable named
var1 cannot be declared in this scope,
| | 04:24 | because it would give a different
meaning to var1, which is already used in a
| | 04:28 | parent or current scope
to denote something else.
| | 04:31 | So these two variables conflict with each other,
| | 04:33 | so I can't do this.
| | 04:36 | It's important to note that this kind
of scope-level referencing only works
| | 04:41 | from the inside out.
| | 04:43 | So if I declare the variable var1 in
here, I can refer to it within the scope;
| | 04:48 | but if I declared it out here then I
would be able to refer to it in this
| | 04:54 | current function-level scope, as well as
all the other scopes that are contained
| | 04:58 | within the function.
| | 04:59 | So for example, I could do
something like this, and that works just fine
| | 05:06 | because the for loop scope is contained
within the scope for the Main function.
| | 05:12 | So in fact if I save this and I run
it, you'll see that var1 is getting
| | 05:17 | incremented by 10 each time and now that
last little console, that WriteLine that
| | 05:21 | I've got that says, what the last
value of var1 was, is working just fine.
| | 05:26 | Understanding variable scope is a
pretty important part of writing good C#
| | 05:31 | code, and it's something that you
should pay close attention to, especially if
| | 05:34 | you're coming from a language like
JavaScript that does not enforce these kinds of rules.
| | 05:38 | This kind of thing can bite
you, so pay attention to it.
| | Collapse this transcript |
| Understanding type conversion| 00:00 | There is one more important concept
that we have to understand in working with
| | 00:04 | C#, and that is understanding type conversion.
| | 00:07 | If you've come from a language like C
or C++ or Java, you've seen this before.
| | 00:12 | Converting one type of variable to
another is called casting, and this is the
| | 00:17 | kind of thing that pops up in languages that
require you to give types to your variables.
| | 00:22 | You're probably wondering, or at least
you soon would be, well, how do I share
| | 00:26 | data between variables that are different types?
| | 00:29 | The way that you do this is by
casting one type of variable to another.
| | 00:34 | It's how you convert data types among
different kinds of data-type variables.
| | 00:39 | So for example, suppose I had an
integer named i and it is set to the value of
| | 00:44 | 10, and I also had a float and
that was set to the value of 20.0.
| | 00:50 | Suppose I wanted to set f to the value
of i. I can just do f=i, and that's okay,
| | 00:57 | because that's an implicit cast, or
a conversion from an int to a float.
| | 01:03 | Since an int is 4 bytes and a float is
larger, there is no risk of data loss here.
| | 01:08 | The integer can simply be
converted into a float and all is well.
| | 01:12 | The reverse is not true.
| | 01:14 | If I said i is equal to f, that causes
an error, because you need to explicitly
| | 01:20 | cast from the float to the
int, because data might be lost.
| | 01:25 | You can't fit all the precision of a
float into an integer automatically.
| | 01:30 | However, if I did this, if I said i is
equal to, and then in parentheses I put
| | 01:35 | the word int in front of the variable
that I'm casting from, that's now okay.
| | 01:41 | I've explicitly cast, or converted, from the
floating-point value to the integer value.
| | 01:48 | You'll see this all over languages like C and
C++ and Objective-C and Java, and now in C#.
| | 01:55 | So let's go over to the code and
actually see it in action. So here I am!
| | 01:57 | I've got my Conversion project open,
and I'm going to open up my Snippets file.
| | 02:03 | That's right there.
| | 02:04 | So let's go ahead and scroll down to
the Conversion section, and that's right
| | 02:10 | here, Type Conversion.
| | 02:12 | So I'm going to copy those lines, and I'm
going to paste them in here. A couple of things.
| | 02:20 | You can see that I've got an
integer, a short, and a float.
| | 02:24 | So in this case, the integer starts
out as 10 and the short starts out as 5.
| | 02:31 | Now, you'll notice that I can simply
assign the value of x to the value of i. Why?
| | 02:36 | Because x is a short. It's 16 bits,
whereas the int is 32 bits, so there is
| | 02:41 | no loss of data here.
| | 02:42 | That's okay; the complier doesn't complain.
| | 02:44 | However, if I try to go the other way,
if I try to set the value of i into x,
| | 02:51 | well, there is data loss here, or
there's potential data loss here.
| | 02:54 | What's going to happen is I've got 32
bits trying to go into a 16-bit bucket, and
| | 02:58 | you can see that little squiggle is saying, hey!
| | 03:00 | Error, cannot implicitly convert type 'int' to
'short', are you missing a cast? Well, yes, I am.
| | 03:05 | All I'm going to do is say--if I put
the word short in front of the i variable
| | 03:13 | inside parentheses, that
says to the compiler, hey,
| | 03:16 | compiler, take the value of i and
explicitly convert it into a short.
| | 03:21 | Now, you notice that that little red
squiggle has gone away, and everything is just fine.
| | 03:26 | So let's go ahead and put a
Console.WriteLine in here.
| | 03:36 | We'll write value x, and we'll write
out x. So let's put a Console.ReadLine at
| | 03:49 | the bottom, and let's also
comment out that error for the moment.
| | 03:56 | So let's save it and run it.
| | 03:58 | You can see that the value of x is 5. Why?
| | 04:01 | Because here we put x into i, and then
we just put i back into x, and since x
| | 04:07 | started out as 5, that's what's
happened, so now x is back to being 5.
| | 04:11 | So let's suppose we comment this
line out and we make i something that a
| | 04:18 | short can't handle,
| | 04:20 | so something like 800,000.
| | 04:23 | So now when we run this, you'll see
that the value of x is 13,568. Why?
| | 04:30 | Because some of the bits of
the integer got stripped off.
| | 04:34 | Remember, the integer is
32 bits, but the short is 16 bits.
| | 04:38 | So 16 bits of information got stripped
off, and what was left over was what could
| | 04:43 | fit in those 16 bits,
and that worked out to be 13,568.
| | 04:48 | So that's the kind of thing you need to
watch out for when you're working with
| | 04:51 | type conversion because some types
of containers are larger than others.
| | 04:55 | Let's go back to the code here.
| | 04:57 | Let's go ahead and get rid of these
two lines. And let's look at the floating-
| | 05:02 | point versions instead.
| | 05:04 | So here you can see I have the
floating-point number f, which is equal to 20,
| | 05:11 | and here I've got the i, which is now 800,000.
| | 05:14 | Again, I can assign the value
of i into the value of f. Why?
| | 05:18 | Because floats are larger than
integers; that works just fine.
| | 05:21 | Same story down here.
| | 05:22 | I'd have to actually cast the float
to be an integer, and in order for that
| | 05:29 | to work, I simply put the word int
inside parentheses, and now that converts
| | 05:34 | the value of the float into an integer,
which can be stored inside the integer variable.
| | 05:39 | You'll see this kind of thing all
over C# code, and you'll see it in
| | 05:43 | other languages as well.
| | 05:44 | It's important to understand how
conversion and casting works because you'll be
| | 05:47 | using it in your own code.
| | Collapse this transcript |
|
|
5. Custom Classes and ObjectsObject orientation refresher| 00:00 | Up until now, I have been talking how
C# is an object-oriented language, and
| | 00:05 | you've been seeing me use objects
throughout some of the previous examples.
| | 00:08 | And we've reached the point now in the
course where we actually need to learn how to
| | 00:11 | define and use our own objects in C#.
| | 00:13 | If you are going to be a C#
programmer, there's no getting around the
| | 00:16 | object-orientedness of the language,
and now is as good a time as any to take
| | 00:20 | a look at how to get started
with the object orientation in C#.
| | 00:24 | So as I have mentioned many times C# is
of course an inherently object-oriented
| | 00:28 | language. There's no getting around
this, and in fact, everything that we have
| | 00:31 | been doing up until now has
involved objects in one way or another.
| | 00:35 | The variables that we've been defining,
those are objects--those integers and
| | 00:38 | strings and everything else.
| | 00:40 | We have been using the console object
to write output to the console window, and
| | 00:45 | even the program itself that
we've been using is itself an object.
| | 00:49 | So objects are everywhere in C#,
and your programs will not be any different.
| | 00:54 | Programs are basically collections of objects.
| | 00:56 | So objects contain data, and they
contain the logic that operates on that data.
| | 01:01 | It's a way of keeping related
data and logic in the same place.
| | 01:05 | And of course objects can communicate
with each other, because if they didn't
| | 01:08 | communicate with each other, not a
whole lot of useful work would get done. And of
| | 01:11 | course not only do the objects
communicate with each other, they communicate with
| | 01:15 | the program that hosts them, because the
program itself is an object, and this is
| | 01:19 | how your programs communicate
with the .NET framework as well.
| | 01:22 | In C# there are three main terms
| | 01:24 | you are going to have to keep track of:
| | 01:25 | there is class, there's
interface, and there is object.
| | 01:29 | Interface is a little bit advanced, so we
are not going to focus on that right now.
| | 01:33 | We are just going to focus on the
class and object terms for the remainder of
| | 01:37 | this section, and we'll see a
little bit about interfaces later on.
| | 01:41 | Classes in C# are one of the most
common type that you will come across, and a
| | 01:45 | class essentially provides a blueprint,
or a description, of what an object looks
| | 01:51 | like and what it does.
| | 01:52 | The blueprint, or description if you will,
defines things like what kinds of data
| | 01:57 | that an object of a certain type holds,
and it also defines what kinds of things
| | 02:01 | that an object can do.
| | 02:03 | It's important to keep in mind,
however, that a class is just a definition.
| | 02:06 | It's a description.
| | 02:07 | It's not the actual object itself.
For example, when you have a blueprint of a
| | 02:11 | house, the blueprint you can think of as
being a class, but it's not the actual house.
| | 02:16 | When you build the actual house, that's
the object; the blueprint just provides a
| | 02:20 | description of how to do that.
| | 02:22 | In your C# programs, you'll usually
defined your own classes to do whatever
| | 02:27 | custom work you need to get done, as
well as using the classes that are provided
| | 02:32 | by the .NET framework.
| | 02:33 | The .NET framework is pretty full featured.
| | 02:35 | It provides hundreds of classes for
doing all different kinds of things, and
| | 02:39 | you'll take advantage of these classes as
you build your own applications. For example,
| | 02:43 | suppose we were building an
application that managed the list of to-do items.
| | 02:48 | You can imagine that we would
have a class to handle the to-do items;
| | 02:51 | we would probably have another class to
group all of those to-do items in a to-do list.
| | 02:56 | And these are classes that your program
would define. But there's a whole bunch
| | 03:00 | of other classes that the .NET
framework would provide for you, things like
| | 03:03 | dates and times and array lists and
classes for working with strings and
| | 03:07 | communicating with the Internet.
| | 03:09 | These are all provided by the .NET
framework, and as you build your applications
| | 03:13 | and learn more about C# and .NET, you'll
use more and more of the .NET classes to
| | 03:18 | round out your applications' functionality.
| | 03:20 | So what do classes define?
| | 03:22 | Classes essentially define two major
things, and these are called the members.
| | 03:27 | The first set of things is fields and
properties and the second set of things are
| | 03:32 | methods or functions.
| | 03:34 | Nowfunctions and methods are pretty
much the same thing, but the word method
| | 03:38 | is what's commonly used in object-oriented
terminology, so that's what I am going to use here.
| | 03:42 | The fields and properties are the kinds of
data that the object holds and works with.
| | 03:47 | The methods are what the object can do;
| | 03:50 | this is their logic, the
functionality that contains in the object.
| | 03:54 | Again, if you go back to our to-do
list item example, you can imagine that a
| | 03:57 | to-do item might have a name, a
description and a priority, then something
| | 04:02 | like a due date, and then we would
need to have methods to operate on that
| | 04:05 | data--for example, setting the description
and changing the priority, and marking items complete.
| | 04:10 | These are what classes defined and as
you build your own classes, you will define
| | 04:14 | your own fields and properties, and you
will write your own methods to work on
| | 04:17 | those pieces of data.
| | 04:19 | Classes can also inherit attributes and
methods from other classes, and this is
| | 04:26 | a very important concept in object-oriented
programming, so it's important that you understand this.
| | 04:31 | For example, let's imagine that I have a class that I
want to define called class A, and class
| | 04:36 | A contains a couple of fields like name
and age and it has a function in it--in
| | 04:41 | this case it called sayHello().
| | 04:42 | Now you've probably already seen
examples like this, and in C# you would refer to
| | 04:47 | these fields and functions by using
the dot notation. So you would say A.name,
| | 04:51 | A.age for the fields,
and A.sayHello() to call the method.
| | 04:56 | I can also define a class that
inherits from class A, and in object-oriented
| | 05:01 | terminology this is called creating a subclass.
| | 05:04 | So if I want to create a class B that
inherits from class A, I would define
| | 05:09 | class B, put a colon after its name,
and then put the name of the class that the
| | 05:15 | class inherits from.
| | 05:16 | So here you can see the class B with
the colon and the A means this class B and
| | 05:21 | it inherits from class A. And in class
B, I've defined a couple of things. I've
| | 05:25 | got another property called
address and a function called sayGoodbye.
| | 05:29 | So again you would refer to this using
standard.notation for the class B, like
| | 05:34 | B.address and B. sayGoodbye. But because
the class B inherits from class A, it
| | 05:39 | also has all of the fields
and properties that class A has.
| | 05:42 | So class B also has a sayHello
function and the name property, even though I
| | 05:46 | haven't defined it in class B; it
just gets all those things because it
| | 05:50 | inherits from class A.
| | 05:52 | So in object-oriented terminology,
we say that class B is a subclass of class A,
| | 05:58 | and class A is class B's superclass.
| | 06:02 | You'll see these terms used throughout
object-oriented documentation whenever
| | 06:06 | you read documentation on web.
Especially in MSDN, you'll see terms like that.
| | 06:11 | You can think of C# objects as
being a kind of stamping machine.
| | 06:17 | So classes, as I mentioned earlier, are
used to create individual objects, and each
| | 06:22 | object that is created from a
class is called an instance.
| | 06:25 | So you can think of this as some kind of
machine that stamps out physical parts.
| | 06:28 | Suppose I had a class definition called
person and the Person class had the name and age
| | 06:33 | and SayHello function.
| | 06:35 | Each time I made an object,
that's called creating an instance of class person.
| | 06:41 | So here I've got three
instances of the Person class.
| | 06:44 | I have got person A, B, and C, and each
one of these real objects has actual data
| | 06:49 | that's filling out the class.
| | 06:51 | So we're using the class
definition, or the blueprint, to actually make
| | 06:55 | instances of that class.
| | 06:57 | So why would you use classes and objects?
| | 06:59 | Well, using classes and objects,
especially in C#, which is objected-oriented
| | 07:03 | language, really makes it easier
to maintain and build applications.
| | 07:07 | First, it helps abstract ideas away
from a specific implementation, which allows
| | 07:12 | you to focus on the core parts of the program.
| | 07:15 | Since the .NET framework provides a
whole bunch of classes that cover common
| | 07:19 | areas of functionality that you don't
have to write yourself, you can focus
| | 07:22 | on building the specific parts of
your program that are only pertinent to
| | 07:26 | your business logic.
| | 07:27 | You can then reuse all the classes that
.NET provides for you, which really makes
| | 07:31 | developing applications a
lot faster and a lot easier.
| | 07:34 | Using classes and objects also helps
encapsulate the programs functionality
| | 07:38 | into understandable pieces, because
each object has its related data and logic
| | 07:43 | all kept in one place.
| | 07:45 | To go back to want to-do list item
example, each to-do item would have not only
| | 07:49 | the information about that particular
to-do item, but the logic that operates on it.
| | 07:53 | So you wouldn't have different pieces
of logic scattered all over the place in
| | 07:56 | different locations without
knowing where each one is.
| | 07:59 | It just makes it easy to understand
the way that an application works.
| | 08:03 | It also helps organize a program
into natural parts that could be easily
| | 08:06 | extended, and this is sometimes referred to
in the object-oriented world as factoring.
| | 08:11 | Once you have factored your
application into its natural parts, the object
| | 08:15 | itself and the program comes to
mirror real-world constructs and ideas.
| | 08:19 | Again, taking a page from out to-do
list example from earlier, when you make
| | 08:23 | objects that mirror real-world constructs
like a to-do item and the to-do list and so on,
| | 08:29 | that makes the program a lot
easier to understand and go back in and
| | 08:31 | maintain years later.
| | 08:33 | So using classes and objects is a really
fast and easy way to build applications
| | 08:38 | that you can maintain in the future and
other people can work on as well and get
| | 08:41 | up to speed on quickly.
| | 08:43 | So we reach the point now where we've
completed our refresher into the world of
| | 08:47 | object-oriented programming, and we are
going to spend the rest of this section
| | 08:50 | seeing how to define classes in C# and
build our own object-oriented programs
| | 08:56 | in .NET and C#.
| | Collapse this transcript |
| Defining a class| 00:00 | Probably the best place to start when
we define our own classes in C# is to see
| | 00:04 | how we define a class
before we can start using them.
| | 00:07 | So we are going to take a look here
at how to define a class using C#, and
| | 00:11 | then we are going to take a look at how to use
it as we move through the rest of the section.
| | 00:16 | So to define a class in C# you use,
surprise, the class keyword.
| | 00:21 | So you say the word class, and then you
have to give it a name. In this case, I
| | 00:25 | am going to use myClass. And you can
use whatever combination of letters and
| | 00:30 | numbers you want, as long as it starts
with a letter and is a valid C# class
| | 00:33 | name--you can have special
characters or anything like that.
| | 00:36 | So I've got class myClass, and then I am
going to define some curly braces, which
| | 00:41 | are going to define the code for this class.
| | 00:44 | Once we have got the class definition
laid out here, we can start adding some
| | 00:49 | fields and some methods.
| | 00:51 | You can add fields and
methods in whatever order you like.
| | 00:54 | You can define field and then method and
then field and then method if you want to.
| | 00:58 | My practice that I use is and I define
all the fields upfront near the top, and
| | 01:03 | then I put all the methods at the bottom.
| | 01:06 | So let's define some fields.
| | 01:07 | I have got two fields here:
| | 01:08 | one is called myInteger;
one is called myMessage.
| | 01:11 | We have got an integer and a string.
| | 01:13 | We could use whatever data types we'd like.
| | 01:15 | In this case, I have just
got a couple for examples.
| | 01:18 | Then I am going to define a method.
| | 01:20 | And here I have defined a function
called myFunction, or method--whatever word
| | 01:25 | you want to use--and it returns an integer.
| | 01:28 | In this case, it returns the myInteger
field. So when the code that uses this
| | 01:33 | class calls myFunction, it will
simply return the value of myInteger.
| | 01:37 | For the moment, don't pay too much
attention to that word "public" that's in
| | 01:41 | front of the word "int."
| | 01:42 | We are going to get into what that
means a little bit later in this section.
| | 01:46 | For now, just assume that the word
public means we have to put it there so that
| | 01:50 | the rest of the world can see this function.
| | 01:53 | This is pretty much a complete class definition;
| | 01:55 | we could just stop here if we wanted
to. But it's customary in C# to define
| | 02:00 | what's called a constructor.
| | 02:01 | A constructor function has
the same name as the class.
| | 02:06 | So to define the constructor--
you can see I have done that here--
| | 02:09 | I've got a method call myClass, and in
this case is this method is taking a
| | 02:13 | string argument which uses the value of
the argument to set the initial value of
| | 02:17 | the myMessage member field. And again,
| | 02:21 | I have got the work public in front
of it, and I don't want to pay too much
| | 02:23 | attention on that right
now--we will get into that.
| | 02:25 | But what I have done here is defined
what's called a constructor, and the
| | 02:29 | constructor takes the same name as the
class itself. And you can give it however
| | 02:34 | many arguments you want, or you
can give it no arguments at all.
| | 02:37 | Now, if you don't define a constructor,
the C# .NET framework will automatically
| | 02:42 | put one in for you. But it is
customary to define one, because you use
| | 02:46 | constructors all the time to
initialize the value of class fields.
| | 02:50 | So now that we've done that, we can go
ahead and take a look at how we might
| | 02:54 | create and use an object
using a class that we've defined.
| | 02:58 | So in C#, the way that you create, or to
use object-oriented terms instantiate, an
| | 03:05 | object is to use the
keyword "new." And it's an operator,
| | 03:08 | so the way that you do this is use you
use the type of myClass, and that's the
| | 03:12 | class that we defined earlier.
| | 03:14 | Then you give it a variable name, myObj.
| | 03:16 | So here instead of saying int and then
some myInteger, which is a built-in C#
| | 03:21 | .NET type, we are using the type that
we've defined called myClass. And we have
| | 03:25 | got a variable called myObj,
and then we simply say = new myClass.
| | 03:30 | And in this case we're passing in a
string to the constructor function--
| | 03:34 | this is how the constructor gets called--
so that string will become the initial
| | 03:38 | value of that myMessage field.
| | 03:41 | To use the fields and methods of a class that
you have instantiated, you use the dot operator.
| | 03:46 | And again, we've seen this throughout the
course so far, but let's just make it official.
| | 03:49 | So let's imagine I have an integer called
myResults and this is some variable I have created.
| | 03:54 | I can then refer to the methods or fields
of the object by using the dot notation.
| | 04:00 | So in this case, I'm calling some
imaginary function called AddNumbers on my object.
| | 04:04 | We haven't defined it yet,
but we could. And you can see it takes two
| | 04:07 | arguments, and then it
returns an integer result.
| | 04:10 | So use the dot operator to reference
the fields and methods of the class.
| | 04:14 | Classes can also have special
members called static members.
| | 04:19 | Static members don't require you to
create, or instantiate, an object's instance
| | 04:24 | in order to use them.
| | 04:26 | That may sound kind of weird, but we've
actually seen this throughout the course so far.
| | 04:30 | Every time we've used the console
object, for example, you notice that we
| | 04:34 | haven't had to say "new console."
| | 04:37 | We simply use the name of the class,
which is console, and then dot and then
| | 04:41 | the word WriteLine.
| | 04:42 | So we are calling what's called a static,
in this case, a member method, called
| | 04:47 | WriteLine, and it belongs to the entire class.
| | 04:50 | You don't have to have it be part
of a specific instance of that class.
| | 04:55 | So let's take a look at the difference
between instance members and static members.
| | 04:59 | Instance members of a class--
| | 05:01 | whether it's a field or a method--get
copied each time a new object is created.
| | 05:07 | Static members, however, belong to the
entire class, and there is only one of them.
| | 05:11 | So let's take a look at an example.
| | 05:13 | Let's imagine we have a class that
defines the notion of a bottle of wine.
| | 05:17 | For each bottle of wine, you are going
to have something like a year and name
| | 05:21 | to go along with it, and you would
have a constructor function that looks
| | 05:25 | something like this, where when you
create a new instance of the wine bottle.
| | 05:29 | you will pass in the name and the year.
But suppose we wanted to keep track of
| | 05:33 | how many bottles we had in our cellar.
| | 05:35 | Well, it seems a little silly for each
instance of the wine class to keep track of
| | 05:38 | its own bottle count;
we only need one variable to do that.
| | 05:41 | So we would have a static member
called bottleCount. And in this case,
| | 05:46 | bottleCount belongs to the entire
wine class, and each instance of the wine
| | 05:50 | bottle will be able to reference this member,
but it doesn't belong to any one of them;
| | 05:54 | it belongs to the entire class.
| | 05:56 | So here in the constructor, we don't
need to refer it to using the class name,
| | 05:59 | because we are in the constructor for
the class. But if we're using code that
| | 06:03 | was outside the class--again, think
back to the Console.WriteLine example--
| | 06:08 | we would simply put the name of the
class in front of the function, and that
| | 06:11 | says to the C# compiler, hey, I'm
calling the static member called this
| | 06:15 | function, or whatever it is--
| | 06:17 | in this case, its not a function at all;
it's a member of variable--
| | 06:20 | and I am referring to the variable
that belongs to the entire class.
| | 06:24 | So let's take a look at some code that
makes all this work, and then it will
| | 06:28 | become a little bit clearer.
| | 06:30 | So over here in C# Express, I've got
my DefiningAClass example open. I have
| | 06:35 | also got my ExampleSnippets.txt
file open, and I've scroll down to the
| | 06:39 | DefiningAClass section.
| | 06:40 | So I am going to start off by
copying some of this code over.
| | 06:43 | So we will copy over the class
definitions, just a few of these lines right here.
| | 06:48 | And the nice thing about C# is you can
put the code anywhere in the class file.
| | 06:51 | Now I could make a separate file to
contain the wine class, but we will do that
| | 06:55 | a little bit later. For now in this
example, I am going to have the two classes
| | 06:58 | be in the same file.
| | 07:00 | So now we have defined the class called
myClass and we've got a couple of members here.
| | 07:04 | We have an integer and a string member,
and you can see that we have declared
| | 07:07 | a static integer called myStaticInt. And again,
don't worry about that public keyword for now;
| | 07:12 | we'll just get to that a little bit later.
| | 07:14 | Okay, let's go back over here, and let's copy
over the functions, and we'll put those in the class.
| | 07:27 | So now we have a complete class definition.
| | 07:30 | We have our member variables;
| | 07:32 | we have a function called myFunction,
which returns an integer--in this case,
| | 07:36 | it's the myInteger member; and
we have the myClass Constructor.
| | 07:40 | When we call the myClass constructor,
we're initializing the values of myInteger
| | 07:44 | and myMessage to some initial values.
| | 07:47 | And we also have the myStaticInt,
which is being initialized to the value of 100.
| | 07:52 | So now let's copy some code over that
actually exercises the class and see what happens.
| | 07:58 | I will just copy these lines right here,
scroll down to the main function and put them in.
| | 08:11 | So let's take a look at the
code and see what's happening.
| | 08:16 | The first thing that we are doing right
here on line 30 is we are instantiating
| | 08:20 | a new instance of the myClass object,
and once we've done that, we can then use
| | 08:26 | the various members of the class.
| | 08:29 | So on line 32, you can see that we
are using the console to write out the
| | 08:33 | results of myFunction. And in this case,
we are using the instance, which is the
| | 08:38 | myC variable, to call the myFunction
member function. And in the next line, line
| | 08:43 | 33, we are going to use the static
member. But instead of using the myC
| | 08:47 | variable, we are going to use the
myClass name, because it's a static member, and
| | 08:52 | we need to refer to it on the class name itself.
| | 08:55 | So we are going to go ahead and build
and run this, and what we should see is the
| | 08:59 | result of calling myFunction.
Let's just scroll back up here.
| | 09:03 | So myFunction is going to return
myInteger, which you can see on line 21 is being
| | 09:08 | initialized to 50, and then we have
the value of myStaticInt, which is 100.
| | 09:12 | So let's go ahead and run this, and you
can see that the results of calling
| | 09:16 | myFunction is 50 and using
the static member is 100.
| | 09:20 | Let's go back to the code.
| | 09:22 | Using this example, you can see how we
have defined member variables which are
| | 09:27 | both local to the instance of an object
and the static member which belongs to
| | 09:31 | the entire class, and we've seen how
to define and instantiate a new class
| | 09:36 | using the new operator.
| | 09:37 | As we move through the rest of the
course, we will be doing a lot more of this.
| | Collapse this transcript |
| Using access modifiers| 00:00 | The C# language provides a feature
called access modifiers, which allow you to
| | 00:05 | control how the member variables and
methods of your classes are seen by the
| | 00:10 | outside world--in others
words code that uses your objects.
| | 00:14 | And if you're coming for the
language, like Java or C++, you've probably
| | 00:18 | seen something similar.
| | 00:19 | JavaScript does not have this kind of
idea in it, so if you're coming from
| | 00:24 | JavaScript, you might want
to pay attention to this.
| | 00:26 | So by default when you define data and
methods in your class, those data fields
| | 00:32 | and methods can only be used
inside of that class itself.
| | 00:36 | You have to choose to expose them to other
code that's going to consume your classes,
| | 00:42 | and this is what access modifiers let you do.
| | 00:44 | They let you specify how programs--
including your own--that use your classes can
| | 00:49 | access their data and their methods.
| | 00:52 | So let's take a look at how this works.
| | 00:54 | Suppose we had a class and I have a
class here called myClassName, and we've
| | 00:59 | got some fields in it.
| | 01:00 | So we have got an integer, and we've got a
string, and we have some method called myFunction.
| | 01:05 | By default, all of these are what's
called private. Only the class that
| | 01:10 | defines these can use it.
| | 01:13 | We need to change that in order for
code that wants to consume our class to be
| | 01:17 | able to access the members of this class.
| | 01:21 | The way that we do that is by
using what's called access modifiers.
| | 01:24 | And if you watch the preceding the
movie, you'll have probably noticed me
| | 01:28 | using the word "public."
| | 01:29 | Well, there are a couple of different
ways to expose members of the class to
| | 01:33 | code that wants to use them.
| | 01:34 | So let's take a look. The first
one is called the private modifier.
| | 01:39 | When you use the private
access modifier, it means that the member of the class
| | 01:44 | who is marked as private can only
be accessed within the class itself.
| | 01:48 | Now this is the default setting, so if
you don't specify private, the C# compiler
| | 01:54 | defaults to making a member
variable or a member method as private.
| | 02:01 | The next one is public. A public
class member can be accessed by any other
| | 02:07 | object that uses the class, and this is
why I was using the public keyword in
| | 02:11 | the previous examples so that our code can
consume that particular member of the class.
| | 02:17 | The next one is called protected.
| | 02:20 | A protected class member can only be
accessed within this class or any subclass--
| | 02:26 | in other words a class
that inherits from this class.
| | 02:30 | So we have got private, we have
got public, and we have got protected.
| | 02:33 | So there is one more, and it's called
internal, and this is a class member that
| | 02:37 | could be accessed by any class in
what's called a same assembly. An assembly
| | 02:42 | is a package of code, like a library or another
program, but this is an advanced feature of
| | 02:47 | C#. I am not going to cover it here in
this course. Just know that you might see
| | 02:51 | the word "internal" every now and then.
| | 02:53 | It's sort of like protected, but it
means that only a group of related code
| | 02:57 | can use it. But for the purpose of
this course we are going to use private,
| | 03:00 | public, and protected.
| | 03:02 | So in order to see how his work, let's
jump over to the code and define a class
| | 03:07 | that uses these, and you can see what
happens when you try to use code that uses
| | 03:10 | each one of these access modifiers.
| | 03:12 | So over here in the code I have
got my ExampleSnippets open for the
| | 03:16 | access modifiers example, and over
here I have got my program file.
| | 03:21 | So here is what we are going to do.
First, we are going to define a new class, and
| | 03:24 | in this case we are going to
put the class in a separate file.
| | 03:27 | So what I am going to do over here is I
am going to right-click on the project
| | 03:31 | name called AccessModifiers, and I am
going to go down to the Add submenu, and you
| | 03:36 | can see that I can add items to my project.
| | 03:38 | What I am going to do is I am going
to add a class, and the Add class
| | 03:42 | dialog comes up. And you can see there
is a whole bunch of things that we can
| | 03:45 | add, all kinds of classes.
| | 03:46 | What I am going to do is just make
sure that the default one here in the list
| | 03:49 | called Class is selected, and then I
am going to give my class a name. And in
| | 03:53 | this case I am going to call
it my Wine class. I'm going to click Add,
| | 03:59 | and you can see that the file for
Wine.cs got added, and you can see that the C#
| | 04:07 | Express application has done a whole
bunch to work for us. First of all, it's
| | 04:10 | automatically put the Wine class
into the same namespace as our example.
| | 04:13 | It's included the using statements for
the .NET framework that we are going be
| | 04:17 | using. And right here you can see it
has provide a definition for class Wine.
| | 04:21 | So let's go back to Snippets.
| | 04:22 | What we are going to do now is fill out
that wine class with some default code.
| | 04:29 | So I am going to copy these lines here.
| | 04:31 | I will go back to my Wine class,
and I am going to paste them in.
| | 04:35 | So now in our Wine class we
have a couple of different members.
| | 04:38 | We have the wine name,
| | 04:40 | we have the wine price, and we have the
wine description. And you can see that all
| | 04:43 | of those are public,
| | 04:44 | so any code that wants to use this Wine
class will have access to those member variables.
| | 04:50 | We have a decimal variable here called
discount, and that's marked as private.
| | 04:56 | So nobody outside this class can see
what that is. And then we have a public
| | 05:00 | constructor, which takes a wine name and
a price. And inside the constructor you
| | 05:05 | can see that we've got the name and
price public variables that are being set to
| | 05:10 | the arguments that are being passed to
the constructor, and then we give the
| | 05:13 | discount variable and initial value as well.
| | 05:16 | And we can do that here because this
is our class and we can refer to our own
| | 05:21 | private members within our own class.
| | 05:23 | So let me save this,
and let's go back to the snippets.
| | 05:28 | Now let's go ahead and copy over some code.
| | 05:30 | I want to copy these two lines first,
and we are going to go to the main function,
| | 05:33 | and I am going to paste tem in.
| | 05:35 | So here you can see that I have got
two instances of the Wine class being
| | 05:40 | created, and I am passing in some
default values for names and prices.
| | 05:44 | So let's write some code now that
exercises some of the fields of the class.
| | 05:48 | So for example, if I wanted to refer
it to the name of one of the wines, I
| | 05:52 | could simply write string and give it a
variable name, =, and I could say w1.
| | 05:57 | And now watch what happens when I press dot.
| | 05:59 | Now when I press the dot, C# Express
is looking at the class description and
| | 06:03 | saying, okay, what can the code in this
particular area see inside that class?
| | 06:08 | And we have got a couple of default
things, because we always derive from the
| | 06:11 | base system object, but here's the name
and the price fields that I've defined.
| | 06:16 | Here is the description field, because
those were all public, and you can see that
| | 06:19 | this is an alphabetized list. What's missing?
Well, the discount field is missing. Why?
| | 06:24 | Because it's private,
and because it's private, my code can't see it.
| | 06:28 | So I can go ahead and refer it w1.Name
all I want to, but if I try to refer to
| | 06:33 | the discount field--let me
make a decimal and we'll call it dsc--
| | 06:38 | if I say w2.discount, now watch what
happens. I am going to save this. See, that
| | 06:45 | little red squiggle showed up and if we
mouse over that little squiggle, we say
| | 06:49 | error. It says the AccessModifiers.
Wine.discount is inaccessible due to its
| | 06:54 | protection level. Go back over to the wine code.
| | 06:57 | You can see that this is private, so
private members can't be referred to
| | 07:01 | outside of the class that defines them.
| | 07:04 | Now we could also have made it protected,
and protected would also result in an
| | 07:08 | error, so let's just change that.
| | 07:09 | Let's just make this private and make
this protected, and we will save, and we
| | 07:14 | will go back over to the program, save
and compile. And you can see that we still
| | 07:19 | have that same error there, right, even
though we made it protected, because in
| | 07:22 | this case we don't have a class that
descends from wine, so it's not inheriting
| | 07:28 | the discount field, and because its
protected, only subclasses can see it.
| | 07:32 | So this is how you use the various
access modifiers of C# to selectively expose
| | 07:39 | member variables and member functions
to code that's going to consume their
| | 07:42 | objects. And the reason you want to
do this is because in good programming
| | 07:46 | practices, you don't want to
just make everything public.
| | 07:48 | You want choose how you expose your
code to consumers of your code. That way you
| | 07:53 | can change the way things are
implemented inside your class without breaking
| | 07:57 | people that are consuming
the class in other programs.
| | 08:00 | So using access modifiers, you can
selectively expose parts of your program
| | 08:05 | to other consumers.
| | Collapse this transcript |
| Defining properties| 00:00 | Okay, I promised you we would get to
some really cool features of C#, and we're
| | 00:04 | about to do that right
here with defining properties.
| | 00:05 | Properties are a really neat feature of the
C# language, and I really like using them.
| | 00:11 | In this section, we're going to
explore what they are and how they work.
| | 00:13 | Properties are essentially like data
fields, but they have logic behind them.
| | 00:18 | And from the outside, they look like
any other member variable, but they act
| | 00:23 | like a member function.
| | 00:25 | They actually have code behind them.
| | 00:26 | Now you define them like you would a
member variable, but they have a get and a
| | 00:32 | set section of code added.
| | 00:34 | And they can use access modifiers just
like member fields and member methods can,
| | 00:40 | and we explored those earlier.
| | 00:43 | Let's take a look at an example
of what a property looks like.
| | 00:47 | So let's imagine we had a class called
myExample and we had some private member
| | 00:50 | variable called someValue.
| | 00:52 | Now because this is private, there is
no way for someone who's consuming this
| | 00:57 | class to get at that data.
| | 00:59 | Now we could make it public, which
exposes the implementation of the class to the
| | 01:04 | outside world, which is not a
very good programming practice.
| | 01:06 | You really want to keep the inner
workings of your class private and then choose
| | 01:10 | to selectively expose data.
| | 01:12 | We could also just make a member
function, which would allow an external consumer
| | 01:17 | of this class to get the
value and set the value.
| | 01:19 | Or we could make what's called a property.
| | 01:22 | A property is defined like this.
I'm making a public integer property called
| | 01:28 | CurrentValue, and instead of making
it look like a member of function with
| | 01:33 | parentheses and arguments and so on,
all I have to do is define the name of
| | 01:38 | the property with two curly braces
and inside I put the word get. And
| | 01:43 | the word get here is essentially
going to return the value of that private
| | 01:48 | integer that I have.
| | 01:49 | And then to set this value, I have the word set.
| | 01:53 | And in the set code, I'm setting the
internal someVal property to this word value.
| | 02:00 | And value is implicit.
| | 02:01 | C# just simply generates that for you.
| | 02:03 | Let's see how this actually
works when you consume this.
| | 02:06 | So to do this, I would define myEX
variable, which is an instance of the
| | 02:11 | myExample class. And I'm
creating a new myExample object there.
| | 02:15 | If I wanted to get the
value, I would just do this.
| | 02:17 | I have an integer i, and I say myEX.CurrentValue.
| | 02:22 | That will trigger the get logic.
| | 02:24 | And in this case, the
get logic is pretty simple.
| | 02:26 | It's returning the value of
that internal private variable.
| | 02:29 | And if I wanted to set it, I would do this:
| | 02:31 | myEX.CurrentValue = 5,
and that will trigger the set logic.
| | 02:35 | And the value of that special value
keyword there in the set logic would be set
| | 02:40 | to an integer whose value is 5.
| | 02:43 | The C# language and .NET just
takes care of all that for you.
| | 02:46 | You don't have to declare
some argument called value;
| | 02:48 | it just magically shows up.
| | 02:51 | So you can have automatic properties.
| | 02:54 | Let's suppose, for example, I had my
class, which I declared up above in the
| | 02:58 | previous example. So I've got myExample
class here with my private someVal int,
| | 03:02 | and I've got the get and the set.
| | 03:04 | Since all that this example is doing
is getting and setting the value of that
| | 03:09 | private internal variable,
| | 03:10 | I can rewrite this very simply, just like this.
| | 03:14 | I have my class, and then I have my
property, and all I do is have the words get
| | 03:19 | and set, and that's all I need to do.
| | 03:21 | This is called an automatic property.
| | 03:25 | You can also have read-only properties,
and you can have write-only properties.
| | 03:29 | Read-only properties and write-only
properties are properties that can only be
| | 03:31 | read and can only be written.
| | 03:33 | So let's take a look at an example.
| | 03:35 | Using the same example we've been
using up until now, I have my example class
| | 03:38 | with my private variable. And inside
my public int CurrentValue, I have get
| | 03:44 | and return someVal.
| | 03:45 | Now if I don't define a set, then the property
is read-only because there is no way to set it.
| | 03:50 | All I can do is get the property.
| | 03:52 | Alternately, I can define just a set.
| | 03:55 | If I don't define a get,
then the property is write-only.
| | 03:59 | You'll very rarely see write-only properties.
| | 04:01 | Properties are pretty useless.
| | 04:02 | You can't actually get their value.
| | 04:04 | But you can do this.
| | 04:05 | So if you don't define a get, or you
don't define a set, then the property is
| | 04:09 | either read-only or write-only.
| | 04:12 | All of this is pretty fun, but why would
you use properties? A couple of reasons.
| | 04:16 | First, properties can be calculated on the fly.
| | 04:19 | So if you wanted to expose a property
that looks like a member variable but has
| | 04:24 | some logic behind it that actually gets
calculated on the fly whenever it gets
| | 04:27 | accessed, read, or set, then
you can use a property for that.
| | 04:31 | Properties also provide complete
control over the data field access, because the
| | 04:35 | logic is hidden from the object's consumer.
| | 04:38 | The consumer of the object's property
doesn't need to know how it's calculated,
| | 04:41 | or what's being calculated.
| | 04:42 | And if later on down the line you go
back and you change the way this object
| | 04:46 | works and the way that that property is
calculated changes, then the people who
| | 04:51 | are consuming your object
don't need to worry about that.
| | 04:52 | They just simply go ahead and keep on
referring to that property, but the logic can change.
| | 04:58 | Properties also promote
the idea of encapsulation.
| | 05:01 | We've talked about this a
couple times before in this course.
| | 05:03 | What you're doing is you're taking the
logic that implements that property and
| | 05:06 | you're hiding it from the consumer.
| | 05:08 | So they don't need to worry about how it works.
| | 05:11 | Let's take a look at an example of
how you'd have a property whose value is
| | 05:14 | calculated on the fly.
| | 05:16 | Let's imagine I had a class that
represented a wine, and in that class, I have a price.
| | 05:23 | I could define the price as just a
public member variable, like I've done here.
| | 05:28 | And I've got some private ones, like
say that there is a wholesalePrice and
| | 05:32 | there is a retailMarkup.
| | 05:33 | So when a wine store buys wine,
they don't pay the retail.
| | 05:36 | There is a wholesale price they pay,
and then there is a markup that they apply
| | 05:40 | to the wholesale price
which is what the real price is.
| | 05:43 | So rather than having a public member
variable, I could expose a public property.
| | 05:48 | And you can see here I've only defined a get;
| | 05:51 | there is no set here.
| | 05:53 | And when the consumer of this Wine
object wants to know what the price of the
| | 05:56 | wine is, you can see that the logic
inside the getter is simply multiplying the
| | 06:01 | wholesalePrice times
whatever the retailMarkup is.
| | 06:04 | So I can have some code that goes out
and figures out what my retail markup is
| | 06:08 | based on some other
parameters I've got in my business,
| | 06:10 | and the consumer of this Wine class
has no idea how or why I'm doing that.
| | 06:15 | They just simply ask what the retail
price is by accessing the property and it's
| | 06:19 | calculated for them on the fly.
| | 06:21 | Let's jump over to the code and define
some properties in one of our classes
| | 06:24 | and see how this works.
| | 06:26 | I'm here in my DefiningProperties
example, and I've got my ExampleSnippets open
| | 06:32 | right here. And I've scrolled down to the
Properties section, and I've got a Wine class here.
| | 06:38 | So what I'm going to do is go back
over to the program code, and I'm going to
| | 06:42 | make a separate class file for my Wine
class. And this just promotes the idea of
| | 06:46 | encapsulation. And we've already done
this once before, but if you skipped over
| | 06:49 | that part, or you need a
refresher, just follow along.
| | 06:51 | So I'm going to right-click on the
project name, and I'm going to click Add, and
| | 06:56 | then at the bottom of the Add menu,
I'm going to add a class. And I'm going to
| | 06:59 | call this my Wine class.
| | 07:00 | First, I'm going to make sure that
the Class option is selected there,
| | 07:04 | and then I'm going to come down here and
type in Wine.cs, and I'm going to add that.
| | 07:11 | Visual C# Express has
made a new Wine class for me.
| | 07:14 | Let's go back over to the Snippets,
and let's just copy this class in its entirety over.
| | 07:23 | Copy this into the Wine class, and let's save that.
| | 07:29 | So now we have our Wine class defined.
| | 07:31 | Let's go back over to the program,
and let's copy in some other code from the
| | 07:35 | Snippets, which is right here.
| | 07:43 | First, let's just copy these few
lines, and we can explain what's going on.
| | 07:51 | Let's take a look at the Wine class to see
what we've done, before we go any further.
| | 07:56 | Here is my custom-built object.
| | 07:57 | It's a class that encapsulates the
notion of a wine bottle. And you can see I've
| | 08:02 | got several private members here.
| | 08:05 | And because they're private, code that is not
inside this class can't see them. So I have a Name.
| | 08:10 | I have a Year.
| | 08:11 | I have an appellation, which in the
wine world is where the wine comes from.
| | 08:15 | I have a wholesalePrice, and then I have
a retailMarkup of 1.35, so I've got 35%
| | 08:20 | markup on whatever wine I buy.
| | 08:23 | Then I've got a property called
Price, and you can see that the price is
| | 08:27 | being calculated on the fly by
multiplying whatever the wholesalePrice is
| | 08:30 | times the retailMarkup. And in
the setter case, I'm setting the
| | 08:34 | wholesalePrice to the value.
| | 08:36 | So I'm not actually setting
an internal price variable;
| | 08:39 | I'm just setting the wholesalePrice which
would have been calculated by the retailMarkup.
| | 08:44 | I also have a property which is a
string called the menuDescription.
| | 08:47 | And if you've ever been in a restaurant,
you've probably seen this. Wines are
| | 08:50 | usually described on wine lists as
having the year, followed by the name, and
| | 08:54 | sometimes where they've come from.
| | 08:56 | So I've got a string property that's
being built up on the fly right here from
| | 09:00 | the private internal properties that I have.
| | 09:02 | And then I have my public constructor,
and the constructor is what creates a new
| | 09:07 | instance of the Wine object.
| | 09:09 | And it's just taking a bunch of
arguments and setting them into the private
| | 09:13 | internal member variables.
| | 09:14 | So let's go back over to the program,
and you can see here that I'm instantiating
| | 09:19 | a couple of instances of the Wine class.
| | 09:21 | I've got a year for each one, I've got
a name, and then I've got a string that
| | 09:25 | explains what the origin is, and then I
have a wholesale price which is going to
| | 09:30 | be used to calculate the retail price.
| | 09:32 | So let's go back over to the Snippets.
| | 09:34 | Let's do some exercising here.
| | 09:35 | We're going to write out
some of these property values.
| | 09:37 | I'm going to just copy
these lines of code right here.
| | 09:39 | I'm going to go back over and paste them in.
| | 09:44 | In the first case, I'm going to write out the
menuDescription and the Price of the two wines.
| | 09:52 | So I've got Wine 1 and Wine 2.
| | 09:53 | And remember, back in the Wine
class, each one of these properties is
| | 09:57 | being built on the fly.
| | 09:58 | So I'm going to save, I'm going to
build, and I'm going to run this.
| | 10:04 | And you can see that I've got
Wine 1 is a 2003 Chateau Ste.
| | 10:07 | Michelle Merlot, from Seven Hills,
and it's $31.72. And then I've got a
| | 10:12 | Mark Ryan Dissident
that's from Ciel du Cheval, and that's $54.
| | 10:16 | But remember, those aren't the
numbers that I put into the constructor.
| | 10:19 | If you look at the
constructor, I've got 23.50 and 40.
| | 10:22 | The reason why those numbers are
coming back differently is because--let's go
| | 10:25 | back over to the Wine class--is
because of this logic right here on line 20.
| | 10:31 | On line 20, I'm taking the
retailMarkup and multiplying it by
| | 10:34 | the wholesalePrice.
| | 10:35 | But from the point of view of the code's
consumer--let's go back to the program--
| | 10:39 | you can see all I'm doing is
accessing this Price property.
| | 10:41 | I don't have any knowledge of how
that's being generated behind the scenes.
| | 10:45 | Let's go ahead and change the
wholesalePrice of one of the wines using the
| | 10:48 | setter, and then we'll write out
the new price. Paste that in here.
| | 10:57 | What we're doing now is using the
setter logic of the Price property.
| | 11:01 | Here I'm changing the
wholesalePrice of Wine 2 to $45,
| | 11:06 | and then I'm going to write out the
wine description, and notice how the retail
| | 11:10 | price has automatically changed
because of that calculation logic.
| | 11:14 | So I'm going to just run this.
| | 11:16 | And you can see that in the first case
| | 11:18 | it's $54, but because of the price that
I set here in the setter, the new retail
| | 11:24 | price is being calculated as $60.75.
| | 11:26 | Okay, let's go back to the code.
| | 11:29 | The reason why I use properties is
because you want to encapsulate some logic
| | 11:33 | inside your class, give it the
appearance of a member variable, but it has logic
| | 11:38 | behind it that determines how that
property is calculated on the fly.
| | 11:42 | And you can use this technique to
expose private internal data in your class in
| | 11:46 | a controlled fashion, and you
can get really creative with this.
| | 11:50 | Suppose, for example, I wanted to
log every time somebody changed the
| | 11:54 | wholesale price of a wine.
| | 11:56 | Well, here in the setter logic,
I could just simply add some code that would
| | 12:00 | write out to a log file when the price
was changed. Or let's suppose I wanted
| | 12:04 | to use my debugger to set a breakpoint on
whenever a value of the property was changed.
| | 12:10 | You can't do that on a private internal
variable, but you can do it on a property.
| | 12:14 | So properties are really versatile,
and they make your code a lot easier to
| | 12:17 | encapsulate and expose and make
consumers use the classes in a way you feel best
| | 12:21 | they should be used.
| | Collapse this transcript |
| Understanding value and reference types| 00:00 | Now that we've learned how to create
our own classes in C#, we've come to an
| | 00:04 | important point in the course where
we need to learn the difference between
| | 00:07 | value types and reference types.
| | 00:09 | C# has two main types:
| | 00:11 | there's value types and there's reference types.
| | 00:14 | Value types are all of the primitive
types that we've learned about so far,
| | 00:19 | things like integers and longs and
shorts and decimals and chars and
| | 00:23 | booleans and so on.
| | 00:24 | And there's also a thing called struct,
which we haven't covered yet, but we
| | 00:28 | will cover later on in the course.
| | 00:30 | Anyway, those are the value types.
| | 00:32 | Reference types are classes, arrays,
and a couple of things called delegates and
| | 00:37 | interfaces which, again, we haven't
yet covered, but we will cover later.
| | 00:41 | So why is there this difference,
and what's so important about it?
| | 00:45 | The main difference between value
types and reference types is how they
| | 00:49 | are handled in memory.
| | 00:51 | And the best way to learn
this is to see an example.
| | 00:54 | So we're going to compare the
value types with the reference types.
| | 00:57 | Now, for a value type, let's
take a really simple example.
| | 01:00 | Let's suppose I have a variable i and I
declare it as an integer and I set its value to 5.
| | 01:06 | Now, when I do that, the C# compiler
goes out in memory and makes a little box
| | 01:09 | called i and it puts the value 5 in it.
| | 01:12 | If I declare another variable called
j and I set it equal to i, then the
| | 01:17 | compiler sets aside another little box,
and this little box is called j, and it
| | 01:20 | also gets the same value as i, which is 5.
| | 01:24 | Now, the important thing to remember
here is that j is a copy of the value
| | 01:28 | that's stored in i right now.
| | 01:30 | So if I go back and change the value
of i to 3, the value of i gets changed,
| | 01:35 | but the value of j does not get changed,
because these are different memory locations.
| | 01:39 | Now, let's compare that
with how reference types works.
| | 01:42 | So suppose I made a class called Point,
| | 01:45 | and inside my Point class I
had two integer member variables
| | 01:49 | X and Y, which represent
the coordinates of the point.
| | 01:53 | To create a new Point, I would declare
a Point class variable named P1, and I
| | 01:59 | would use the new operator to create
a new instance of the Point object.
| | 02:03 | Then I could do something.
| | 02:04 | Now since these are public member variables,
I could say P1.X and P1.Y are equal to 10.
| | 02:11 | Let's watch what happens in memory.
| | 02:12 | Well, in memory, that little location
called P1 for the variable gets created,
| | 02:17 | but what also gets created is a set
of bytes somewhere else in memory that
| | 02:21 | actually hold the member variables.
| | 02:23 | And P1 is not actually containing that data.
| | 02:27 | It contains a reference to that data.
| | 02:30 | There's this little reference that goes out
into memory and knows where X and Y are stored.
| | 02:35 | So let's suppose I made
another variable called point P2.
| | 02:39 | And rather than doing new
Point, I say point P2 = P1.
| | 02:44 | Well, that creates a little
local variable there called P2.
| | 02:47 | But watch what happens.
| | 02:48 | The reference gets set to
the same reference as P1.
| | 02:52 | They're sharing the same reference to
the same location in memory, because I
| | 02:57 | didn't make a new instance of Point;
I simply set P2 to be equal to P1.
| | 03:02 | And when you do that with a reference
type, you're sharing the same reference.
| | 03:05 | What does that mean?
| | 03:06 | Well, if I then do something like this where I
set P1.X =20, it changes for the both of them.
| | 03:12 | So even though I didn't do anything
to mess with P2, P2.X is now having the
| | 03:17 | value of 20, the same way that P1.X is.
| | 03:20 | This is an interesting side effect of
how reference types works, and you need to
| | 03:24 | watch out for it in your code.
| | 03:25 | Let's go over to the code
environment and take a deeper look at this.
| | 03:29 | So I'm here in my ValAndRefTypes
example file, and I've got the Program.cs file
| | 03:35 | open, and I've got my Snippets here.
| | 03:37 | So what I'm going to do is back here in
my code, I'm going to put some code in
| | 03:41 | here that exercises both the
reference and value types that we saw earlier.
| | 03:47 | So let's go back over here.
| | 03:48 | What I'm going to do is copy this
line right here, which is the Point
| | 03:51 | definition, put it into my file over here.
| | 03:54 | I'll just put right in front of
the Program class. I'll save that.
| | 03:57 | And then I'm going to copy over this
function right here called testFunc1.
| | 04:03 | And this is the first test that
we'll run. So I'm going to copy that.
| | 04:06 | I'm going to put that in my program down here.
| | 04:10 | So now let's copy over some of
the logic to see what's happening.
| | 04:13 | Go back to my Snippets.
| | 04:15 | I'm going to scroll down a little bit,
copy these few lines right here, starting
| | 04:20 | with this variable and
down through this WriteLine.
| | 04:22 | I'm going to copy that
and paste it into my Main.
| | 04:27 | So let's take a look at
the code that we have here.
| | 04:30 | We'll use point a little bit.
| | 04:31 | I just want to make sure we have it in place.
| | 04:32 | For now, I'm just going to
concentrate on this code right here.
| | 04:35 | In my Main function I've got a variable
called i, and I'm setting it to be the value of 10.
| | 04:40 | And then I call this function,
testFunc1, with the i variable.
| | 04:43 | So let's scroll down and see what testFunc1 is.
| | 04:47 | You can see it takes an integer argument.
| | 04:49 | And the first thing it does is it adds 10 to
the argument that's passed into the function.
| | 04:56 | When this Console.WriteLine gets
executed, it's going to write out the value
| | 05:00 | of whatever arg1 is.
| | 05:02 | And then when the function completes
and goes back up, we're going to write out
| | 05:05 | whatever the value of i is.
| | 05:07 | Go ahead and place your
wagers and let's see what happens.
| | 05:11 | Build this, and we're going to run it.
| | 05:13 | So you can see that what happened was
we passed the 10 into the function, and
| | 05:19 | arg1 was set to 10, but then we
added 10 to it, so now it's 20.
| | 05:23 | But when we come back out of the function,
the original variable i is unchanged.
| | 05:27 | It's still 10, even though we
added 10 to it inside the function.
| | 05:31 | So let's go back and take a look at the code.
| | 05:33 | The reason why this works is
because for primitive value types, like
| | 05:36 | integers, when you call a function and you
pass in the value as an argument to the function,
| | 05:42 | it is passed as a copy.
| | 05:44 | When you pass value types,
you pass a copy of their original values.
| | 05:50 | So even though we changed the value in
here on line 29, since we're passing in
| | 05:54 | a copy of the local i variable from Main,
we're not actually changing the i variable;
| | 06:00 | we're only changing the local
copy that testFunc1 is working with.
| | 06:04 | Let's go back and copy in the rest of our code.
| | 06:09 | And I'm going to copy in these lines
here, put them in my Main function.
| | 06:19 | And I need to copy over my other test
function, which is this one right over here.
| | 06:27 | And I'll put that down below
here, and now we'll save everything.
| | 06:33 | Now, let's go ahead and run our next
test. And for this I'm going to get rid of
| | 06:36 | these lines of code because we don't need them.
| | 06:39 | So here I'm using the Point class,
which I've defined up above my Main.
| | 06:43 | Here's the Point class.
It's got an x and a y value.
| | 06:46 | So on line 19, I'm creating a new point,
and I set p.x and p.y to both be 10.
| | 06:52 | Then here on line 22 I write out the
value of the X property. Then I call this
| | 06:58 | testFunc2 with p--that's the point--
and then I write out p.x again.
| | 07:04 | Let's see what testFunc2 is doing.
| | 07:06 | Well, testFunc2 takes a
Point argument, as you'd expect,
| | 07:10 | it writes out the value of pt.x, then
it adds 10 to the value, and then it
| | 07:14 | writes out pt.x again.
| | 07:16 | So we're going to write out four things here.
| | 07:19 | We're going to write out the value of
the Point's x field, both inside the test
| | 07:22 | function and outside the test function.
| | 07:24 | So let's go ahead and compile this and run it.
| | 07:27 | And you can see that before we call
the function, the value of p.x is 10.
| | 07:32 | Then we go into the function and pt--
that's the local variable inside
| | 07:36 | that function--is 10.
| | 07:38 | Then we add 10 to it, which gives us
the value of 20, and we write that out.
| | 07:41 | So inside the function,
pt.x has been changed to 20.
| | 07:44 | Then we exit the function and go back
into Main and you can see that the value
| | 07:48 | of p.x has been changed to 20.
| | 07:50 | So in this case the value
was changed. Let's go see why.
| | 07:55 | Remember that Point is a class,
| | 07:59 | and the class was one of those things that
we looked at earlier was a reference type.
| | 08:04 | So when you make a new point like
this here on line 19, and then you pass
| | 08:08 | it into a function,
| | 08:09 | you're not passing a copy;
you're now passing it by reference.
| | 08:14 | And because testFunc2 has a reference
to the original point, if you change it
| | 08:19 | inside the function, it will
change outside the function as well.
| | 08:23 | This is the fundamental difference
between value types and reference types, and
| | 08:27 | it's something you'll come
across in C# on a regular basis.
| | Collapse this transcript |
|
|
6. CollectionsWorking with arrays| 00:01 | In this section, we're going to cover
some of the data structures that .NET
| | 00:06 | provides for you, and specifically
we're going to focus on collections.
| | 00:10 | Collections are essentially classes
that help you keep track of and manage a
| | 00:14 | whole bunch of data, and since a lot of
programming involves keeping track and
| | 00:19 | managing data, it seems like this
is a pretty good place to start.
| | 00:23 | We're going to start off
by looking at C# arrays.
| | 00:26 | Now in C#, arrays hold a fixed
number of elements, all of the same type.
| | 00:32 | An array is basically just
a list of items and values.
| | 00:37 | So for example, if I declared an
integer variable called oneValue and set it to
| | 00:42 | be equal to 100, we've already seen this.
Somewhere out in memory the C# compiler
| | 00:47 | and the .NET framework creates a little
box called oneValue and puts the value
| | 00:52 | inside that little variable box.
| | 00:54 | Now an array is a little bit different than
that, and the way you declare them as a
| | 00:58 | variable is also a little bit different.
| | 01:00 | When you declare an array you specify
the type that you want the array to hold,
| | 01:05 | so here it's an integer just like
always, but then you put these two square
| | 01:08 | little brackets next to the type definition.
| | 01:11 | So you have the opening square
bracket and the closing square bracket with
| | 01:15 | nothing in it, and then you give it the
variable name, just as you always would.
| | 01:19 | And this just tells the Compiler, hey,
| | 01:20 | we're not declaring one integer.
| | 01:22 | We're declaring a whole bunch of integers.
| | 01:24 | And then you complete the sentence by
saying = new and then the type that
| | 01:29 | you're creating, in this case an integer,
and then inside the square brackets you
| | 01:33 | put the number of slots that you want to create.
| | 01:36 | So this line of code right here int, square
brackets, manyValues creates a variable called
| | 01:42 | manyValues, which is an array of,
in this case, four integers.
| | 01:46 | And out in memory what's going to
happen is the .NET framework is going to
| | 01:50 | create some space and it's going to
create a variable called manyValues and
| | 01:53 | there will be four little
boxes all initialized to 0.
| | 01:57 | The .NET framework takes care of
initializing the array for you so that they are all 0.
| | 02:01 | Now arrays are zero-based indexes. So that first
element in the array there is not element 1;
| | 02:07 | it's actually element 0,
and it counts up from 0 up to 3.
| | 02:10 | So there are four
elements, but it goes from 0-3.
| | 02:13 | So if I wanted to reference one of
the elements in the array, I would simply
| | 02:17 | use manyValues and then inside the square
brackets the index number of the one I want to change.
| | 02:22 | So if I wanted to change the first
element in the array to a value of 100, I
| | 02:25 | would say manyValues, subzero, =100,
and lo and behold, the value changes.
| | 02:30 | If I wanted to change the last one, I
would do manyValues and then 3 in the
| | 02:34 | square brackets and that works.
| | 02:37 | Just like other variables in C#, I can
also initialize array variables just like
| | 02:42 | I can initialize other variable types.
| | 02:44 | So in this case, I'm declaring an
integer array called manyValues and rather
| | 02:49 | than creating the new memory using the
new operator, I'm using curly braces and
| | 02:53 | then just putting the array values
inside the curly braces, separated by commas.
| | 02:57 | This will create an array of four integers,
just like we saw in the previous example.
| | 03:02 | And of course, I can do this with strings too.
| | 03:04 | I can say string array myStrings = and then
inside the curly braces just four strings.
| | 03:09 | One of the cool things about C# is
that unlike other languages, like say
| | 03:12 | Objective-C, C# provides what's called
automatic bounds checking for arrays.
| | 03:17 | So in programming, if you try to
reference an array index that's outside of the
| | 03:22 | bounds, or the size of the array, some
languages don't check that for you and it
| | 03:26 | can lead to code
problems and bugs down the road.
| | 03:29 | But in C# if I tried to do this,
manyValues and then 100 inside the little
| | 03:34 | brackets as an index, if I try to set that
value, that's going to cause an error. Why?
| | 03:38 | Because there is only four elements
inside the manyValues array, so there is no
| | 03:43 | element 100, and that's going to cause a problem.
| | 03:45 | The good news is, C# catches that for you.
| | 03:48 | Now arrays are fixed in size.
| | 03:50 | Once you declare them,
that's just how big they are.
| | 03:52 | There are other data structures that
we'll get to that allow you to change
| | 03:56 | the size of the array, but when you declare
arrays like this, that's just how big they are.
| | 04:00 | Why? Because this allows them to be
contiguous somewhere in the computer's memory,
| | 04:04 | which is very efficient for the
processor to access and change them.
| | 04:09 | The other thing you need to realize is
that array elements are all the same type,
| | 04:12 | so you can't have an array to clear
like you see it here that has numbers and
| | 04:16 | strings and floats and different data types.
| | 04:18 | When you declare an array using either int
brackets or string brackets or float brackets or whatever,
| | 04:24 | choose your data type brackets,
they're all going to be the same type.
| | 04:28 | Arrays can also be multidimensional.
| | 04:31 | Now in the previous example we
saw a single dimensional array.
| | 04:34 | It was just one list of numbers.
But you can make arrays multidimensional, and
| | 04:38 | the way that you do that is you
declare the type, so for this case, integer.
| | 04:41 | Then inside the brackets you put a little comma.
| | 04:43 | This is going to have two dimensions.
| | 04:45 | It'll have the name of the variable
called multiDimArray. Inn this case I'm saying new int and 3,3.
| | 04:50 | So that's going to make a 3x3 matrix
of memory locations somewhere out in the
| | 04:56 | computer's memory, and it's
going to initialize them all to 0.
| | 04:59 | And then to round out the picture here,
the first number in the index there is
| | 05:04 | going to represent the row number,
and the second number in the index
| | 05:07 | represents the column number.
| | 05:08 | So if I wanted to refer to a specific
box inside the memory of the array here, I
| | 05:14 | would say something like
multiDimArray, 0,1, = 10.
| | 05:18 | That means row 0, column 1 and
that's the one that gets changed to a 10;
| | 05:22 | and just like other arrays,
you can initialize these too.
| | 05:25 | So to do that, I would have the int,
the type declaration, along with my little
| | 05:30 | brackets with the comma inside,
and then I would just give the variable a name.
| | 05:33 | And in this case I have new int, comma,
withinside the curly braces a set of curly
| | 05:39 | braces, each one representing a row of data.
| | 05:42 | This would create a 3x3 array with all of
the boxes set to (0,1,2), (3,4,5), (6,7,8).
| | 05:50 | So you can initialize them and you can
make multidimensional arrays with set values.
| | 05:56 | Now arrays, of course, are, just
like everything else in C#, objects.
| | 06:00 | So, for example, if I had this
declaration here for int manyValues = 100, 200
| | 06:06 | and so on, that gives me an
array object with four entries in it.
| | 06:11 | So I can then do something like this.
| | 06:13 | I can say manyValues.
| | 06:15 | and then call a function called
GetLength(), and that will come back with a
| | 06:18 | number four, because how many there are.
| | 06:20 | I can also call some static member
functions. Remember, we talked about
| | 06:23 | static items earlier on.
| | 06:25 | I can do Array.Clear and then give it the
name of the array and a couple of indexes.
| | 06:30 | Then starting at 0, it'll
clear out the four elements.
| | 06:33 | I can do Array.Sort.
| | 06:35 | It will sort the given array, assuming
that the members of the array are sortable.
| | 06:39 | Same thing with Reverse.
| | 06:41 | I can just reverse the given array.
| | 06:43 | Because arrays are objects, you get
access to a whole bunch of built-in features.
| | 06:47 | So let's exercise some of these features.
| | 06:48 | Okay, here in the code I've got my
Arrays example open, and I've got my Snippets
| | 06:54 | here. Scroll down to Arrays,
and here's my program code.
| | 06:57 | So let's just go ahead
and copy some of these over.
| | 06:59 | I'm going to do the first couple of
lines right here, and we'll paste that in.
| | 07:04 | And here what we're doing is we're
just declaring an array called manyValues
| | 07:07 | that has a whole bunch of values in it,
and then we're going to write out the
| | 07:10 | value of the fourth number.
| | 07:12 | And remember, to do that, since this is the
fourth number and it's a 0-based index,
| | 07:15 | we use the number 3,
and set right here on line 13.
| | 07:18 | So let's hit F5 to run this,
and the fourth number is 34.
| | 07:22 | Okay, that's pretty simple and straightforward.
Let's keep on going.
| | 07:25 | In this case, we'll do
the same thing with strings.
| | 07:29 | So here I have an array of strings.
| | 07:31 | I've got four strings: Joe, Marini, Teaches, C#.
| | 07:34 | And what I'm going to do here is use a
for loop to write out the values of each
| | 07:38 | one of the elements.
| | 07:39 | So I have a for loop going from 0,
and notice I'm using <4 here, not < or =,
| | 07:45 | because it has to stop at 3.
| | 07:46 | I'm going to write out each one of
the strings using the i variable here to
| | 07:52 | index into the array.
| | 07:53 | So once again I'll hit F5,
and you can see that works just fine.
| | 07:57 | Okay, so let's keep on going because
this is getting interesting.
| | 08:00 | Let's go back over here.
| | 08:02 | We'll copy and paste this
and put that down here.
| | 08:06 | So here you can see that I've created
an integer array called otherValues and
| | 08:10 | I've set it equal to manyValues,
and now I'm changing the last item in the
| | 08:16 | otherValues array to 0.
| | 08:17 | But what I'm writing out over here is
the manyValues array, or at least the last
| | 08:23 | element of the manyValues array.
| | 08:25 | Now see if you can guess what's going to happen.
| | 08:28 | If we look at the item here, you can
see that manyValues(3) is 0, 1, 2,
| | 08:31 | 3; it's currently 34.
| | 08:34 | Let's see what happens when we change
the otherValues array or sub three to zero.
| | 08:38 | I get it set to 0. Why?
| | 08:40 | Because remember arrays are reference types.
| | 08:43 | We passed in a reference to the array;
therefore we actually changed the value of
| | 08:48 | both manyValues and otherValues.
| | 08:50 | And if you skipped the section earlier
on value types versus reference types,
| | 08:54 | you should go back and review it now.
| | 08:55 | Let's try something else.
Let's try some sorting.
| | 08:57 | I am going to copy this.
| | 08:58 | I'm going to paste it over here.
| | 09:02 | So now I'm calling the array
class's Sort static member function on
| | 09:08 | my manyValues array.
| | 09:09 | And when I do that, we're going to
write out what the fourth number is.
| | 09:12 | So let's go ahead and build that,
and you can see that the fourth number is 16.
| | 09:18 | So we sorted the array going
from smallest to largest, and that's a
| | 09:22 | built-in feature of .NET.
| | 09:24 | Arrays are really useful
collection objects to use in C#.
| | 09:27 | You will find yourself using
arrays for all kinds of things.
| | 09:30 | Arrays are used for processing lists of
information and so on. What we'll take a
| | 09:34 | look at next is a collection type
called ArrayList, which has some added
| | 09:37 | benefits on top of arrays themselves.
| | Collapse this transcript |
| Using array lists| 00:00 | All right. The next collection class that
I am going to cover here is ArrayLists.
| | 00:05 | Now ArrayLists are like arrays,
but there are a couple of unique features to them.
| | 00:10 | First, they can be
dynamically resized as needed.
| | 00:13 | Recall from the previous movie that
arrays are set in size once you create them;
| | 00:18 | ArrayLists aren't like that.
| | 00:19 | Now the way you create an ArrayList is
by using the ArrayList class. And here
| | 00:25 | I've got an ArrayList with a variable
named myAL, and I just say new ArrayList.
| | 00:31 | And we'll see how to do
this in a bit in the code.
| | 00:34 | You have to include another namespace in order
to use these, but the class name is ArrayList.
| | 00:39 | And in this case, I'm just calling
the constructor that doesn't take any
| | 00:43 | arguments, but there is a
version that does take an argument.
| | 00:45 | I could also just declare this variable
by saying new ArrayList and then give it
| | 00:49 | some number, which is the capacity
that I wanted to start off with.
| | 00:52 | If you don't do this, it starts off
with some default capacity, and I don't
| | 00:56 | remember what is on the top of my
head. I think it's like 10 or 50 or
| | 00:58 | something like that.
| | 00:59 | But you can say new ArrayList with a
hundred or a thousand if you know you're
| | 01:02 | going to start off with a
number that's that large.
| | 01:05 | So to add and remove items from the
ArrayList, you use the functions that go
| | 01:11 | along with the ArrayList class.
| | 01:13 | So for example, to add an object to the
ArrayList, you would simply call myAL.Add.
| | 01:19 | And notice that items get added as objects.
| | 01:22 | It takes an object as its argument.
| | 01:24 | But remember, everything in C# is an object--
| | 01:27 | well, almost everything anyway.
Certainly all of the primitive data types and
| | 01:31 | any of the classes that
you're going to come up with.
| | 01:33 | So you can add objects into your ArrayList.
| | 01:36 | Now you can add, which puts them at the
bottom, or you can use the Insert method,
| | 01:40 | which takes an object and puts it in
at a specific index. And then to remove
| | 01:44 | things you can use the Remove and RemoveAt.
| | 01:46 | So the Remove function takes the
object that you're passing as an argument,
| | 01:50 | finds it in the ArrayList, and removes it.
| | 01:52 | RemoveAt removes the object that is at
the index that you pass in, and remember
| | 01:57 | indexes here are zero-based.
| | 01:58 | There is also an easy way to find out
how many things there are in the ArrayList.
| | 02:03 | There is the myAL.Count, which is a
property on the ArrayList that tells you how
| | 02:08 | many items are currently in the ArrayList.
| | 02:11 | You can also do indexing with ArrayLists
the same way that you would do them
| | 02:14 | with regular arrays.
You can do things like myAL subzero.
| | 02:16 | You can even set values this way, which
I guess is okay to do, but my preference
| | 02:23 | is to use the functions
that come with the class.
| | 02:25 | Okay, let's take a look at ArrayLists and loops.
| | 02:29 | So suppose we had an ArrayList that we
declared like this and we added a whole
| | 02:34 | bunch of items, items 1, 2, 3 and 4.
| | 02:36 | Out in memory this goes ahead and
creates an ArrayList with four items in it.
| | 02:41 | Now if we want it to loop over the
contents of this array, there is a couple
| | 02:45 | ways we could do it.
| | 02:46 | We could use the for loop, which we've
seen in the past. And in this case, we
| | 02:50 | would have an integer variable named i
and we would loop i up to being less than
| | 02:55 | the count of the items in the array,
and we would increment the loop counter.
| | 02:59 | Now this is a perfectly valid way of doing this;
| | 03:01 | however, there is another way to do this.
| | 03:04 | And of course we could operate
on the contents of the ArrayList.
| | 03:06 | We could write things out.
| | 03:07 | But my preference when working with
things like this is to use the foreach loop.
| | 03:13 | Now we didn't talk about this earlier in
the course, but I'm going to introduce it now.
| | 03:16 | The foreach loop construct loops over
all of the elements in a collection, and
| | 03:21 | you can use it with arrays
and other things throughout C#.
| | 03:24 | We're going to do it with ArrayList right here.
| | 03:27 | So foreach doesn't take a loop counter.
What you do is you declare a variable
| | 03:31 | inside those parentheses; in this case it's
an object because ArrayLists contain objects.
| | 03:36 | So you would say foreach (object obj in,
and then the name of the collection.
| | 03:41 | In this case it's myAL. That's my ArrayList.
| | 03:44 | And then we can go ahead and
operate on each object inside the loop.
| | 03:47 | So rather than doing the myAL sub-I that
you see there in the loop, we would change
| | 03:52 | that to Console.WriteLine and then obj,
because obj is going to be set to a
| | 03:57 | different object each time through the loop.
| | 03:59 | That's basically how foreach works.
| | 04:01 | It's really nice because there's
no loop counters to keep track of.
| | 04:04 | There is no comparisons to make.
The foreach construct just knows how to loop
| | 04:09 | over all the elements of a
collection and put it into an object's variable
| | 04:14 | that you declare here.
| | 04:15 | Well, in this case it's an object;
it could be other things too.
| | 04:18 | But in this case it's an object
because ArrayLists keep track of objects.
| | 04:21 | ArrayLists can also have mixed
content, unlike arrays. So if we declare an
| | 04:27 | ArrayList that looks like this,
and then we go and add content to it using the
| | 04:32 | Add, remember each one of
these is added as an object.
| | 04:36 | So I've got strings. I've got numbers.
| | 04:38 | I can put anything I want in here, as
long as it derives from system.object,
| | 04:42 | which all the primitive value types do
and all the reference types that we've
| | 04:46 | talked about, they do as well.
| | 04:48 | So I can do things then like this.
| | 04:49 | I can have an integer variable named
result, and once again, I'm going to use my
| | 04:53 | foreach construct. And in this
case, remember they are all objects,
| | 04:57 | so for each object in the ArrayList,
I can then do something like this.
| | 05:02 | If the object is an integer--remember the
is operator from earlier on in the course--
| | 05:09 | I can then say result +=, and then I
cast, or convert, the object to an integer by
| | 05:15 | putting the word int in
parentheses in front of it.
| | 05:18 | So this is going to loop over
each object in the ArrayList,
| | 05:21 | see if it's an integer, and if it is
an integer, add it to a running total.
| | 05:25 | So ArrayLists are really nice and flexible.
| | 05:27 | Let's go ahead over to the code
and see some of this in real action.
| | 05:30 | Okay, here in the code I've got my
ArrayLists example open, and I've got my
| | 05:35 | ExampleSnippets file. I'll scroll down to the
ArrayLists section, and I'm going to copy
| | 05:39 | these lines right here, and I'm
going to paste them into my program.
| | 05:44 | Put those into Main.
| | 05:45 | All right, so let's go ahead and take a
look at the lines of code and see what they are doing.
| | 05:50 | Here on line 13 I'm declaring a new
ArrayList object, then putting it into the
| | 05:55 | myAL variable, and then I add
some stuff to the ArrayList.
| | 05:59 | I've got a string, integer, another
string, another integer, and then a
| | 06:02 | floating-point number.
| | 06:04 | Then I have my foreach construct right
here on line 20, and I've got my object o
| | 06:10 | variable, and that's going to be set to
whatever the current object is each time
| | 06:15 | through the loop. And then I'm checking
to see if o is an integer, and if it is
| | 06:19 | an integer, I write out the value of o
using the Console.WriteLine construct.
| | 06:25 | So let's run this, and you can see
that 2 and 4 are being written out.
| | 06:30 | Okay, let's go back and
make a quick modification.
| | 06:33 | Let's say for each object, if o is an
integer or o is a float, then we'll write it out.
| | 06:45 | In this case, we'll run it again,
| | 06:47 | you can see that the floating-point number
as well as the integers are being written out.
| | 06:51 | So ArrayLists are really nice
flexible alternative to using arrays in C#.
| | 06:56 | If you find yourself needing an array
construct that is flexible, can contain
| | 07:01 | mixed content, and so on, consider
using ArrayLists rather than just fixed-
| | 07:05 | sized arrays.
| | Collapse this transcript |
| Working with stacks| 00:00 | The next collection class that we are
going to look at is called the stack.
| | 00:05 | Stacks maintain a list of items just
like arrays and ArrayLists do, but they
| | 00:10 | operate on a slightly different paradigm
called push-on and pop-off, and you can
| | 00:15 | think of a stack as, like, in fast food
restaurants they have those cup stacks
| | 00:20 | where they push all the cups into the
holder and then each time a person takes a
| | 00:24 | cup, it pops off the top.
| | 00:26 | Stacks are pretty much the same way.
| | 00:28 | Stacks are declared by using the stack class.
| | 00:31 | So to declare a stack, I will use the
stack class, and then mystack is the
| | 00:34 | variable name. This is probably
familiar by now. I say new stack.
| | 00:38 | That will create a stack object out in memory.
| | 00:41 | To put data on the stack, I use the
push method to push data on the stack.
| | 00:47 | Remember, these are objects,
| | 00:48 | so I can pass any primitive type or any
reference type, anything I can come up with.
| | 00:54 | In this case, I will just
push a string called a string 1.
| | 00:56 | What that will do is that will put
string 1 onto the top of the stack.
| | 01:01 | If I then push another piece of data,
say string 2, what will happen is string 1
| | 01:05 | will slight down and string
2 will now be the new top.
| | 01:08 | And I can keep on doing this
with successive pieces of data.
| | 01:11 | I can have strings 3, 4, 5, and so on.
| | 01:14 | To get the data off the stack,
instead of using push, I use pop.
| | 01:18 | So I would declare an object variable.
| | 01:22 | In this case, it's called o,
and then I would call mystack.Pop.
| | 01:25 | This would get the top value on the stack.
| | 01:28 | So after calling pop, string 2 pops off
and then string 1 slides back on up and
| | 01:33 | now the value of o is the string 2.
| | 01:36 | If I wanted to just see what was on
top of the stack without changing it, I
| | 01:40 | would use the Peek method.
| | 01:42 | This looks at the top value,
but doesn't actually pop it off.
| | 01:47 | Then finally I can see how many
things there are on the stack by asking the
| | 01:50 | stack's count property
how many things there are.
| | 01:53 | In this case, it will tell me
that there is one item on the stack.
| | 01:56 | Stacks are commonly referred to as LIFO,
| | 01:59 | Last In, First Out, data structures,
because the things that you push onto
| | 02:04 | the stack earlier get pushed down towards the
bottom and later elements are nearer the top.
| | 02:09 | So as you pop them off, those
items are going to come out first.
| | 02:12 | So it's Last In and First Out.
| | 02:14 | Again, stacks are one of the common
data structures you will find throughout
| | 02:17 | programs for various purposes.
| | 02:19 | Let's go ahead and jump over to the
coding environment and actually exercise
| | 02:23 | this to see how it works.
| | 02:25 | So here in the code I have
scrolled down to my Stacks section in my
| | 02:29 | ExampleSnippets, and I have got my Stacks
project open over here with my Main function.
| | 02:36 | Let's go ahead and copy some code over.
| | 02:38 | So the first thing I am going to copy
over is this setup code right here, and I
| | 02:42 | am going to paste that in.
| | 02:45 | Right there on line 13 you can see that
I am declaring a new stack variable, and
| | 02:50 | then I am pushing some data on the stack.
| | 02:51 | I am Pushing strings, items 1, 2, and 3.
| | 02:54 | Then I am just going to write out how
many items there are on the stack by using
| | 02:57 | the mystack.Count property.
| | 03:00 | So we are going to run this, and you
can see that sure enough, there are
| | 03:03 | three items on the stack. So far so good.
| | 03:06 | Let's go back over to the code.
| | 03:08 | Now let's have a peek at what the top item is.
| | 03:11 | So we are going copy that,
and we will paste that below here.
| | 03:16 | Now remember Peek is non-destructive.
| | 03:19 | In other words, it doesn't
actually change the stack;
| | 03:21 | it just shows me what's on the top.
| | 03:22 | So we will run this and you can
see that items 3 in on the top. Why?
| | 03:26 | Because item 3 was the last item pushed on;
therefore, it will be at the top of the stack.
| | 03:33 | So far, things are operating
the way they are supposed to.
| | 03:35 | Let's go ahead and try popping something.
| | 03:37 | I will go ahead and
paste that code in down here.
| | 03:44 | So now here on line 23 you can see I
am calling the Pop function, which is
| | 03:48 | going to pop item 3 off the top of the stack,
which means that item 2 will now be the top item.
| | 03:54 | So when I write this out, it
should say item 2. So let's run this.
| | 03:57 | Yeah, sure enough item 2 is
now on the top of the stack.
| | 04:00 | Let's go back to the
Snippets over here. One more thing.
| | 04:04 | We'll paste that code in here.
| | 04:11 | So now I am going to call these stacks
Clear function right here on line 27, and
| | 04:15 | that will get rid of
everything on the stack here.
| | 04:17 | It will clear out the contents and then when I
call mystack.Count, I should have the value 0.
| | 04:23 | So let's press F5 and sure enough,
I have got 0 items on the stack.
| | 04:30 | You will find stacks used
throughout C# programs and other programming
| | 04:33 | languages in general.
| | 04:34 | They are pretty useful for keeping
tracks of certain kinds of data structures,
| | 04:37 | mathematical expressions, evaluations, and so on.
| | 04:40 | There are a couple of great examples.
| | 04:41 | So that's how you use stacks.
| | Collapse this transcript |
| Working with queues| 00:00 | Well, continuing on with the cavalcade
of collection data structures, we are now
| | 00:04 | going to look at queues.
| | 00:06 | Queues maintain a list of items kind of
like stacks do, but they are different
| | 00:10 | than stacks in that they're FIFO, or
First In, First Out--kind of like a line of
| | 00:15 | people waiting at a counter.
| | 00:16 | In fact, if you've ever spent any
time in UK, you will probably hear lines
| | 00:19 | referred to as queues, and queues in
programming work pretty much the same way.
| | 00:25 | Something enters the queue, and it's the
first one in. It's also the first one out.
| | 00:28 | And items move in the queue in an
orderly fashion, or at least they should.
| | 00:33 | Using queues in C# is similar to using
stacks, only instead of having Last In,
| | 00:39 | First Out, it's going to be First In, First Out.
| | 00:42 | To declare a queue, you use the Queue
class name and here I have got a queue
| | 00:47 | named myQ and I create a new queue.
| | 00:49 | Then to put things on the queue, instead
of using push and pop, we are going to
| | 00:52 | use Enqueue and Dequeue.
| | 00:55 | So in this case, I am going
to create my new myQ variable.
| | 00:58 | I will call Enqueue. And in this case I
am passing a string, but it's an object,
| | 01:02 | so it can be anything;
it could be a number or whatever.
| | 01:04 | So I am passing in a string.
| | 01:05 | When I do that, string 1
will be placed in the queue.
| | 01:08 | If I then Enqueue string 2, string 1
will move down and then string 2 will now
| | 01:12 | be at the back of the queue.
| | 01:15 | Instead of using Pop, I am going to use Dequeue.
| | 01:18 | So when I say Dequeue, the first item
will come off of the queue like this.
| | 01:24 | That leaves string 2 as the current first item.
| | 01:28 | Just like using stacks I can do things
like Peek, and Peek is non-destructive.
| | 01:32 | In other words, it's does
not take things off the queue;
| | 01:34 | it just shows me what's
at the front of the queue.
| | 01:36 | In this case, it's now string 2.
And also like stacks, I can use the Count
| | 01:40 | property to see how many
items are actually on the queue.
| | 01:44 | So since this is so similar to stacks,
let's just go ahead and waste no time and
| | 01:47 | get over to the code so we
can see this working in action.
| | 01:50 | Here we are in the code.
| | 01:52 | One of the things that I haven't
pointed out up until now, which you
| | 01:55 | probably have noticed, is that you
need to include a name space in order to
| | 01:58 | use the collection classes.
| | 02:00 | Up until now we've had a
Collections.Generic which has been included for us by
| | 02:04 | default, but in order to use things
like stacks and queues and ArrayLists, you
| | 02:08 | need to include this guy right
here using System.Collections.
| | 02:11 | This is the namespace you need to
include in order to use the classes we have
| | 02:15 | been talking about so far.
| | 02:17 | So to use queues and stacks and ArrayList and
so on, just make sure you have that included.
| | 02:21 | So let's jump over to the Snippets,
and you can see I have scrolled down to the
| | 02:25 | queue section. And I am going to go
ahead and copy these lines and this is the
| | 02:30 | setup code right here.
| | 02:31 | I'll just paste this in.
| | 02:36 | So right there on line 13, creating a
new queue, and then I am Enqueuing four
| | 02:40 | items. And I am going to write out how
many items there are in the queue and sure
| | 02:44 | enough, there four items, just
like you would expect there to be.
| | 02:48 | Now let's go back to the Snippets.
| | 02:50 | Just to show you that you can use
other kinds of loop constructs with these
| | 02:54 | collection classes, I am
going to use a while loop.
| | 02:57 | And if you have been watching along
with me so far, you've probably noticed
| | 03:00 | I've used for loops.
| | 03:01 | I have used for each loops.
| | 03:03 | It's time to give the while loop its turn.
| | 03:05 | So here I am going to say while myQ.Count > 0
we are going to Dequeue items--
| | 03:13 | you can see they're on line 23--and
then in the following line 24 we are just
| | 03:15 | going to say Dequeuing object
whatever and write it out to the console.
| | 03:21 | Each time we Dequeue something the
Count property is going to automatically
| | 03:25 | be decremented for us.
| | 03:26 | We don't have to worry
about taking care of that.
| | 03:28 | The class keeps track of how many items
there are in the queue. And since Dequeue
| | 03:32 | takes things off of the queue,
the Count will change for us.
| | 03:35 | So I am going to go ahead and compile this
and build this, make sure it works, and it did.
| | 03:38 | Now let's just go ahead and run this.
| | 03:42 | You can see that we are Dequeuing items in the
same order that they were put o to the queue.
| | 03:47 | So item 1 was the first one in, and it's the
first one out, followed by items 2, 3, and 4.
| | 03:52 | So queue is similar to stacks,
only they operate more like a Line.
| | 03:55 | If you find yourself in need of a
collection class where the order is
| | 03:58 | important and you need to process
things in the same order that they come in,
| | 04:02 | use queues instead of Stacks.
| | Collapse this transcript |
| Using dictionaries| 00:00 | The last example of a collection class that
we are going to look at is the dictionary.
| | 00:05 | And dictionaries are used to
associate a particular key with a given value,
| | 00:11 | and you can think of them as lookup tables.
Essentially, you use a key to look up a value.
| | 00:16 | So if I have a dictionary object then I
essentially have a key that's associated
| | 00:21 | with a value inside that dictionary.
| | 00:24 | And some examples of that might be a
product ID with a product name, or I could
| | 00:28 | associate say an abbreviation for
a state name with its full name.
| | 00:32 | But really I can associate any
object with any other object.
| | 00:37 | This is what hashtables
are essentially used for.
| | 00:40 | They are probably one of the most
useful collection classes out of all of them.
| | 00:44 | Keys have to be unique.
| | 00:46 | You can't have duplicate keys,
and dictionaries don't have any sense of order.
| | 00:52 | So unlike other collection classes, like
stacks or queues or arrays, there is no
| | 00:57 | sense of order here.
| | 00:58 | You simply put in keys, associate them
with values, and there's no notion of who
| | 01:04 | is first or who is last.
| | 01:06 | Probably the most common example
of a dictionary is the hashtable
| | 01:11 | or associative array.
| | 01:13 | You probably heard it called many
different names depending on what other
| | 01:16 | programming language you may have come from.
| | 01:18 | If you've never heard of it before
then I will introduce it to you now.
| | 01:22 | The hashtable is an example of a
dictionary, and the Hashtable class in C# is
| | 01:28 | declared the same way you
declare any other collection class;
| | 01:30 | you simply have the Hashtable class,
and in this case I'm declaring a variable
| | 01:34 | named myHT, which is of type Hashtable,
and then you just use the new operator
| | 01:39 | like you would in any other class.
| | 01:41 | So this will create a new hashtable
named myHT, and then we can start adding
| | 01:46 | things to the hashtable. And the way
you do that, well, there are a couple ways
| | 01:49 | to do it, but the first way to
do it is to use the Add function.
| | 01:52 | When you add something to a
hashtable you give it the key that you want.
| | 01:56 | So for example, I could give a
three-letter airport code, like SEA, and then I
| | 02:01 | give it the value, which might be
something like Seattle Tacoma Airport.
| | 02:05 | Then over in a hashtable I would
have a little key named SEA and would be
| | 02:08 | associated with a value.
| | 02:10 | And I could do the same thing for
say SFO, and that associates it with
| | 02:14 | San Francisco Airport.
| | 02:15 | I can also use bracket notation.
| | 02:18 | For example, I can say myHT, and then
in brackets I can have the three-letter
| | 02:22 | code for IAD, which is Washington's
Dulles Airport. And using the bracket
| | 02:28 | notation, I will simply use the equals,
or assignment operator, to say myHT sub
| | 02:33 | ID is Washington Dulles Airport, and that
would also put something into the hashtable.
| | 02:38 | That's how you get data into the hashtable.
| | 02:41 | The way that you get data out of the
hashtable is to use the Remove function.
| | 02:45 | In this case, I would call myHT.Remove,
and then I give it the name of the key
| | 02:49 | that I want to be removed.
| | 02:50 | So if I want to remove San Francisco
Airport, I would simply say Remove SFO and
| | 02:54 | that will cause SFO to be
removed from the hashtable.
| | 02:58 | Just like other collection
classes, there are a couple of utility
| | 03:01 | properties and so on.
| | 03:02 | For example, I can see how many things
there are in the hashtable by using the
| | 03:06 | by now ubiquitous Count property.
| | 03:07 | This will tell me in this particular
case there are two things in the hashtable.
| | 03:11 | I can also see if hashtables
contains certain values by using a test.
| | 03:15 | I can, for example, declare a Boolean
variable name b and call the ContainsKey
| | 03:21 | function on a given hashtable. And I
can pass in a key name, in this case SFO,
| | 03:26 | which will return false now,
because it's gone. Or I can also use the
| | 03:30 | ContainsValue version as well.
| | 03:32 | So I can say, hey, hashtable, do you
contain the value San Francisco Airport?
| | 03:36 | In this case, it's now false, but if
it was still there, it would be true.
| | 03:39 | So let's just jump over to the code and
make ourselves a hashtable and exercise this.
| | 03:45 | So here I am in code.
| | 03:47 | Once again you'll notice I am using
the System.Collections using statement up
| | 03:51 | here that includes the name space for
the collections class, which includes
| | 03:56 | things like dictionaries and
hashtables and queues and stacks and all the
| | 04:00 | examples we have been using so far.
| | 04:02 | So jumping over to the Snippets code,
you can see I have scrolled down to the
| | 04:05 | Dictionary section, and I am going
to copy the setup codes over here.
| | 04:08 | I am going copy that and it
will paste it into the Main.
| | 04:17 | You can see on line 13 I have created a
new hashtable, and then I've added some
| | 04:21 | data to the hashtable.
| | 04:22 | I have added airport codes SFO, SEA,
and IAD, and I have set their associated
| | 04:28 | values to the full names of their airports.
| | 04:31 | Then we can test this out by saying,
hey, let's do a Console.WriteLine to see
| | 04:35 | the value for key, whatever is this.
| | 04:39 | And we are going to pass in the name of
that key. In this case I will look
| | 04:42 | up the value by using the bracket notation.
| | 04:44 | So you can see here on line 16 I use
the bracket notation to set the value.
| | 04:48 | I can also look up the value by using
the bracket notation, but without an
| | 04:52 | assignment operator.
| | 04:54 | So I am going to do a build.
| | 04:55 | You could see the build succeeded,
and we are going to run it.
| | 04:59 | And you can see it worked fine.
| | 05:02 | The value for key SEA is
Seattle Tacoma Airport. That's great.
| | 05:07 | Let's continue on with the exercise.
| | 05:09 | I am going to copy this line here,
which simply tells me how many items there
| | 05:14 | are in the hashtable.
| | 05:15 | So I'll save that and run it.
| | 05:18 | And as you expect, there are 3 items
in the hashtable. So far so good.
| | 05:24 | Let's do our last exercise right here.
| | 05:27 | Copy and we'll paste this in.
| | 05:31 | In this case, we are going to exercise
the Remove functionality, but before I
| | 05:35 | uncomment that Remove line--let's just
go ahead and write it out that right now--
| | 05:41 | you can see that the value for
key SFO is San Francisco Airport.
| | 05:45 | That's because SFO is still in the table;
| | 05:47 | I haven't removed it yet. But if I
uncomment this line right here, I'm going to
| | 05:53 | remove the SFO key, and then the next
line is the if statement on line 22 that
| | 05:58 | says, hey, if myHT contains
the key SFO then write it out.
| | 06:03 | Now that condition is going to
be false, because we've moved it.
| | 06:05 | So let's run it again, and you can see
that this time there was no WriteLine for
| | 06:11 | the SFO key, because it's not there anymore.
| | 06:14 | Hashtables are probably one of the most
useful of the collection classes, and if
| | 06:19 | you're coming from a language like
JavaScript you've probably used these a lot.
| | 06:23 | In fact, they are used all over the world
of programming, and in C# it's no different.
| | 06:27 | You can use hashtables to associate
keys with objects, or any other kind of data
| | 06:32 | that you can think of.
| | 06:33 | They're pretty useful.
| | 06:34 | They are also pretty efficient.
| | 06:36 | If you find yourself in need of
having a lookup mechanism, a hashtable
| | 06:39 | usually fits the bill.
| | Collapse this transcript |
|
|
7. More Complex ClassesOverloading methods| 00:00 | We have reached the section of the
course now where we are going to start
| | 00:02 | learning about some of the more
advanced object-oriented features of C#.
| | 00:07 | The information in this part of
the course is going to build on the
| | 00:11 | information that we learned about
earlier in the chapter on creating custom
| | 00:15 | classes and objects.
| | 00:17 | Go ahead and watch that content if you
haven't already, and then pick it up here.
| | 00:21 | We are going to start with method
overloading, and method overloading is when
| | 00:25 | you define methods that have the same
name but different ways of calling them.
| | 00:30 | So let's look at a real example.
| | 00:32 | Let's go back to our ubiquitous Wine
class example, and you can remember from
| | 00:37 | earlier examples I've got a class
here called Wine. And I can declare some
| | 00:42 | member variables like Year, Name and
Price, as I have done in the past. And you
| | 00:45 | have probably seen me do something
like this where I declare a constructor
| | 00:49 | function called Wine, which is the
same name of the class, and in this case it
| | 00:54 | takes a string argument and it sets the
value of the Name variable to whatever
| | 00:59 | argument was passed in.
| | 01:00 | That's great, but what if I also
wanted to give people that are using this
| | 01:03 | class a way to initialize the class, or
construct the class, with both a name and a year?
| | 01:11 | Well, I could simply just define
another Wine constructor function like this,
| | 01:16 | and in this case I have got a Wine
constructor which takes a string and takes a Year.
| | 01:20 | You might be saying, well, wait a minute.
| | 01:21 | You have already got a
constructor function called Wine.
| | 01:24 | Isn't this a problem? Aren't you redefining
something? No, not really.
| | 01:27 | What I am doing here is I'm overloading
the Wine constructor, and this doesn't
| | 01:33 | just work with constructors.
| | 01:34 | You can do this with any function.
| | 01:35 | I just happened to be doing
with the constructor function here.
| | 01:38 | And the reason this works is because the
signatures of the two methods are different.
| | 01:44 | In other words, the parameters that each
one of these constructor takes is unique.
| | 01:49 | So for consumers who wanted to call
the constructor for the Wine class using
| | 01:54 | just a name, they can do that.
| | 01:56 | If they want to use both the name and a
year in their code, they can do that too.
| | 02:00 | As long as you define the function
with the same name and a different set of
| | 02:05 | parameter lists, that's fine. That's legal C#.
| | 02:08 | Let's take a look at an
example that doesn't work.
| | 02:12 | If I have a class and I wanted to
provide two functions of the same name, here I
| | 02:17 | have got a function that takes an
integer and returns an integer and I've got
| | 02:21 | another function that takes
an integer but returns a float.
| | 02:23 | The problem is this is an error.
| | 02:26 | The return type of the
function is not part of the signature.
| | 02:29 | It's the parameter list.
| | 02:31 | These methods are not considered
different by the compiler. And you can imagine
| | 02:36 | in the code I would call out a
function with an integer argument,
| | 02:39 | the compiler wouldn't know which
one to call. So you can't do this.
| | 02:43 | You can't have functions that
defer only by the return type.
| | 02:46 | The parameter list has to be different.
| | 02:49 | So let's take a look at some
real code to see how this works.
| | 02:52 | So in the MethodOverloading example
I've got my program, opened and here's my
| | 02:57 | Snippets code, and I've scroll down
to the overloading methods section.
| | 03:01 | So I am just going to go ahead and
copy this entire class right here for Wine.
| | 03:07 | And we are going to need this to set up
the example, so I will just copy this in,
| | 03:10 | and I will put it above the program class.
| | 03:15 | Before I copy the rest of the code,
let's take a look at what's going on here.
| | 03:18 | I have my Wine class and I have got my
member variables here, and then I've got
| | 03:23 | a set of constructors.
| | 03:24 | You can see that I've got a constructor
for the Wine class that takes just a string,
| | 03:28 | I have got one that takes a string
and a year, and I've got one that takes a
| | 03:32 | string, a price and a year.
| | 03:36 | So I have got three different
constructor functions, so I am overloading this
| | 03:39 | function three times.
| | 03:40 | Okay, now let's go back to the
Snippets and let's copy in some code that
| | 03:45 | actually exercises this.
| | 03:47 | I will copy that and put it into the Main
function, and we will just put it in right there.
| | 03:56 | You can see here, starting on line 35,
I am creating three Wine objects, w1, w2
| | 04:03 | and w3, and I am calling the
constructor in a different way each time.
| | 04:07 | For w1 I am just passing in a string
by putting in a name, for w2 I have got a
| | 04:11 | name and a year, and for w3 I've got
the name, the price and the year, and
| | 04:17 | then I've got three lines here that's going
to write out the various parts of the objects.
| | 04:23 | So for Wine 1 I am going to
write the name, and so on.
| | 04:25 | Let's go ahead and try this
code out and see what happens.
| | 04:29 | So you can see that when I run the code
for w1, I am writing out just the name;
| | 04:33 | for w2 I have the year and the name; and for
w3 I have got the year, the name, and the price.
| | 04:41 | Now, because I've overloaded these
functions, I can call them with different
| | 04:46 | values and different parameters.
| | 04:47 | So, for example, I have given the
consumers of this class three different ways
| | 04:51 | to build their Wine class objects:
| | 04:54 | so just the name, the name and the year,
and the name and the year and the price.
| | 04:58 | I want to go back and change
the way that I constructed w1,
| | 05:02 | I can put my cursor in here and type
comma. And you can see that when I type the
| | 05:07 | comma, C# Express gives me a little
pop-up that says hey, there are three
| | 05:12 | different ways you can call this function.
| | 05:14 | You can see right here it's on 2 of 3,
but I can cycle through all of these.
| | 05:18 | 1 of 3 is to call the Wine
constructor with just a string.
| | 05:22 | Here is the version with just a string
and an integer. And you can see, since I
| | 05:27 | have put the comma in there, it's
highlighting the integer in bold saying, hey,
| | 05:30 | that's where I think you are going
to type next. Or in the third case,
| | 05:35 | I've got the string, the price, and the
year. And again I am on parameter number
| | 05:39 | two right now so it assumes I
am going to type a price in here.
| | 05:42 | But the point is that C# Express is
looking at my constructor list and helping
| | 05:47 | me choose the one that I want,
and it's showing me what's available.
| | 05:50 | I can choose to use either
this version or this version.
| | 05:53 | So let's go ahead and use the second version.
| | 05:55 | I am going to just type in 2007.
I need to change the Console.WriteLine as well.
| | 06:04 | So I will put this in here w1.Name,
and now I will do w1.Year. And when I save
| | 06:15 | and I rerun this, you can see I have got the
name and the year that's being written out.
| | 06:21 | Just to recap, overloading a method is
when you declare a method with the same
| | 06:27 | name but with a parameter
list that's different each time.
| | 06:30 | In this example I showed you how to do
it with the constructor, but you can do
| | 06:34 | this with any method.
It doesn't have to be the constructor.
| | 06:37 | You can't do this with properties.
You can't do this with fields.
| | 06:39 | You can do this with methods.
| | Collapse this transcript |
| Overriding methods| 00:00 | A very close cousin of overloading
methods is called overriding methods.
| | 00:05 | In overriding methods, you basically
get to change or augment the behavior of
| | 00:10 | methods and classes, and this is
called overriding their logic.
| | 00:14 | It's one of the most powerful things
of object-oriented programming and it
| | 00:18 | really, really helps you when you want
to encapsulate your logic in your objects
| | 00:22 | and separate the behaviors of
different objects from each other.
| | 00:26 | Let's suppose you have a phone. And a
phone knows how to do something, like ring,
| | 00:32 | but of course you just have a phone.
| | 00:35 | You have a particular type of phone.
| | 00:36 | You might have a landline.
| | 00:38 | You might have a cellular.
| | 00:39 | You might have a satellite phone.
| | 00:40 | Well, each of those knows how to ring as well.
| | 00:43 | In fact, they have got their
own custom ways of ringing.
| | 00:46 | Now when you get a phone call the
person calling you doesn't necessarily know
| | 00:50 | what kind of phone you have; all
they know is that you have got a phone.
| | 00:54 | When they make a phone call the system
looks up your phone and tells your phone
| | 00:57 | to ring. And when the phone is told to
ring it figures out what kind of phone
| | 01:02 | you have, and it tells that particular
kind of phone to go ahead and do its
| | 01:06 | ringing. And this is the same kind of concept
that we will do in object-oriented programming.
| | 01:12 | You will have a class, a subClass,
and the baseClass, or the superClass, to use
| | 01:18 | object-oriented terminology,
| | 01:20 | will have some method in it, and you
want to either completely replace the
| | 01:24 | logic that's in that method, or
you want to augment it somehow.
| | 01:29 | You use overriding in order to do this.
| | 01:31 | Now there are three important
things you have to understand.
| | 01:34 | There are three keywords in C#.
| | 01:36 | The first one is virtual.
| | 01:38 | The virtual keyword tells the
compiler that it can be overridden.
| | 01:43 | The override keyword is another
important one, and then there's the base keyword.
| | 01:48 | To use the overriding mechanism,
there are three things you have to do.
| | 01:51 | First, you have to mark a
method as being virtual.
| | 01:55 | This tells the compiler that this particular
method can be overridden by derived classes.
| | 02:00 | If you're coming from other languages
like JavaScript or C++, this may look
| | 02:05 | somewhat familiar,
but it's a little bit different.
| | 02:08 | You have to specifically mark a
function as being over overridable.
| | 02:12 | So here you can see I have got
a function called myFunction.
| | 02:14 | It returns an integer. And I have got
the public keyword in front of it, but I
| | 02:19 | have inserted the word virtual
between the public and the return type.
| | 02:24 | This tells the compiler, hey,
somebody might want to override this.
| | 02:27 | Now they don't have to, but they might want to.
| | 02:29 | To actually override the method, in
the subClass, I tell the compiler that a
| | 02:35 | particular method is going to override
the same method in the baseClass by using
| | 02:39 | the override keyword.
| | 02:41 | So in this case instead
of virtual, I use override.
| | 02:44 | You can see I have done the same thing
here: between the return type and the word
| | 02:47 | public, I've used the word override.
| | 02:51 | And these two go hand in hand
when you want to override methods.
| | 02:55 | Then finally, there is the base keyword,
and you can use this in your subClass to
| | 02:59 | call the baseClass's method. And you
use this because you don't necessarily
| | 03:04 | always know what the name of the baseClass is.
| | 03:07 | Instead of you actually using the name
of the baseClass, you simply say base, dot,
| | 03:11 | whatever the function is. And this
will call into the code in the superClass
| | 03:16 | instead of your subClass.
| | 03:18 | Now there is a little bit complex.
| | 03:21 | It's probably helpful to see
an example of this in action,
| | 03:24 | so let's jump over the code and see it work.
| | 03:29 | So here I am in my example.
| | 03:31 | This is for method overriding. And I am
going to go over to my Snippets, and you
| | 03:35 | can see in my Snippets I have scrolled
down to the Overriding Methods section.
| | 03:39 | The first thing I am going to do
is copy over my class definitions.
| | 03:42 | I have two classes:
| | 03:43 | I have one that's a baseClass and I have
one that is a subClass of that baseClass.
| | 03:47 | Let's go ahead and copy these over, and I
will put these in my program definition here.
| | 03:56 | So now I am going to scroll back over
here down a little bit. I'm going to copy this
| | 04:02 | code and put it into my program.
| | 04:08 | Before we run this, let's take a
look at the class definitions, so we can
| | 04:13 | see what's going on.
| | 04:16 | In my baseClass, you can see here on
line 10 I have got a function called
| | 04:21 | doSomething. And it doesn't return
anything, so it's a void return type and it's
| | 04:26 | public. And I have
declared it as a virtual method.
| | 04:29 | What that means is when I create a
subClass that descends from this baseClass
| | 04:34 | the subClass has the opportunity, if
it wants to, to override this method.
| | 04:38 | Now the baseClass method for
doSomething just simply writes something out to the
| | 04:42 | console. It says, hey, this
is the baseClass saying "hi."
| | 04:44 | Go down to the subClass. On line 18
you can see that I've got the same
| | 04:49 | method, doSomething.
| | 04:51 | In this case I've got the override keyword.
| | 04:54 | So this tells the compiler, hey, I'm
overriding whatever the baseClass does.
| | 04:59 | In the doSomething method for the
baseClass I am calling the baseClass's version
| | 05:03 | of doSomething, which will call the
Console.WriteLine method. And then I can put
| | 05:08 | on whatever additional
programming logic I want to.
| | 05:12 | I can do another Console.WriteLine.
| | 05:14 | I can put it before or after the baseClass call.
| | 05:18 | I can put it here if I want to.
| | 05:19 | I will just leave it there for now.
| | 05:22 | So let's go back down to the program.
And you can see that what I am doing is I
| | 05:25 | am creating an object.
| | 05:27 | I have got a subClass object.
| | 05:31 | I have created a new subClass object
called obj1, and I am going to call doSomething.
| | 05:35 | So let's see what happens when I run this.
| | 05:39 | Two things get written out:
| | 05:41 | "This is the baseClass saying hi!"
| | 05:43 | and "This is the subClass saying hi!"
| | 05:45 | So why did that happen?
| | 05:46 | Well, in obj1 we called doSomething.
| | 05:48 | obj1 is a subClass, so we will look
in the subClass. And you can see that in
| | 05:55 | doSomething the first thing we do is
call the baseClass's version of doSomething,
| | 06:01 | which will be this right here.
| | 06:02 | The baseClass saying hi!
| | 06:04 | gets called first, and then that
returns and then the subClass gets called.
| | 06:08 | We can reverse that order.
| | 06:10 | We can cut this line and put it up here,
and let's run it again, and now you can
| | 06:14 | see that the subClass says hi
first instead of the baseClass.
| | 06:18 | Let's go back to the code.
| | 06:19 | We can actually just take this call out.
| | 06:21 | We don't have to call the
baseClass if we don't want to.
| | 06:23 | Now we've completely replaced the
functionality that the baseClass provides, and
| | 06:28 | we are only doing what the subClass says to do.
| | 06:31 | So we are going to save this and run
it and now you can see that only the
| | 06:34 | subClass's version of that function is
running; the baseClass's version is not
| | 06:38 | getting a chance to run. Hit Return.
| | 06:41 | Let's try something else.
| | 06:44 | Since subClass is a version of the
baseClass object, I can do something like this.
| | 06:52 | I can say baseClass obj1 = new subClass.
| | 07:00 | Now that may seem strange at first,
because wait a second. Shouldn't I be
| | 07:03 | creating a new subClass?
| | 07:05 | No, I'm actually going to
create a baseClass object.
| | 07:07 | Let's see what happens here. Ah!
| | 07:10 | "This is the subClass saying hi!"
| | 07:12 | Why did that happen?
| | 07:13 | Why is it that when I created an
object of type baseClass, or I gave it a
| | 07:18 | name of baseClass, and I created a new
type of subClass, why did it not call
| | 07:23 | the baseClass's version? Why?
| | 07:25 | Because when you create a virtual
function C# is actually going to look up what
| | 07:29 | the lowest descendent is and
call that version of the function.
| | 07:33 | Since I actually created a new instance
of subClass, even though I arranged it to
| | 07:38 | be assigned to a variable named
baseClass type, it's still going to look down in
| | 07:42 | the functions and say, oh, you know what?
| | 07:44 | That subClass object is
actually overriding this function,
| | 07:46 | so I am going to call that version instead.
| | 07:48 | Let's change this so that instead of
creating a new subClass type, I am creating
| | 07:53 | a new baseClass type.
| | 07:55 | Now let's see what happens.
| | 07:57 | I am going to run it.
| | 07:59 | Now it's the baseClass's version saying hi. Why?
| | 08:01 | Because it's not a subClass anymore;
| | 08:03 | it's a baseClass now.
| | 08:05 | That's how you override methods.
| | 08:07 | You use the keyword "virtual" to indicate
that a method can be overridden and then
| | 08:12 | use the "override" keyword to indicate
that you are overriding it in a baseClass.
| | 08:17 | And you can use this to augment the
functionality provided by baseClasses in
| | 08:22 | your own programs, as well as other
programs that you might be adding on to.
| | 08:26 | It's a really great way of
segmenting your program so that pieces of
| | 08:31 | functionality don't have to be changed
in baseClasses in order to provide new
| | 08:35 | pieces of functionality in
classes that derive from them.
| | Collapse this transcript |
| Creating abstract classes and methods| 00:00 | All right, in this section we are
going to talk about abstract classes, and
| | 00:04 | abstract classes tend to be one of
those subjects that trip people up who
| | 00:06 | are learning object-oriented programming for
the first time, so I'll try to make this easy.
| | 00:11 | Essentially, an abstract class
can't be instantiated by itself.
| | 00:14 | You have to create a subclass,
and you have to instantiate that instead.
| | 00:18 | In other words you've got to derive a
class from an abstract class and make
| | 00:22 | that class instead;
| | 00:23 | you can't instantiate an abstract class.
| | 00:25 | abstract classes have abstract members
and these are members that have to be
| | 00:30 | overridden by subclasses in
order to provide functionality.
| | 00:34 | So, okay, why would you do this?
| | 00:36 | Well, there are going to be times in
programming where you define a class that
| | 00:39 | describes an abstract idea,
but it doesn't make sense by itself.
| | 00:43 | It has to have an actual physical
implementation, and that physical
| | 00:46 | implementation is going to change
among different versions of that class.
| | 00:50 | And we'll take a closer
look at that in a moment.
| | 00:52 | First, let's see how to
actually describe an abstract class.
| | 00:55 | Abstract classes are indicated by putting
the word abstract in the class definition.
| | 01:00 | So if I normally describe a class like
this using public class, myClass, and then
| | 01:06 | declare the class normally like
you see me do throughout the course,
| | 01:09 | what I would do here instead is put the
word abstract inside the class definition.
| | 01:13 | That tells the compiler
that this is an abstract class.
| | 01:16 | Then once I've done that, I can declare an
abstract member function, like you see here.
| | 01:22 | Now I don't provide an
implementation for this function here.
| | 01:26 | Remember, I'm forcing the subclass to do that.
| | 01:29 | The subclass has to provide an implementation.
| | 01:33 | So let's take a look at a real-world
scenario where you would do something
| | 01:38 | with abstract classes.
| | 01:39 | Consider an example where you've got a
car dealership or some kind of dealership
| | 01:43 | where you sell different types of vehicles.
| | 01:46 | Now vehicles, depending on what they are,
have unique characteristics, but some of
| | 01:51 | them might be common among all
different kinds of vehicles. For example, they
| | 01:55 | might have properties like what kind of
fuels they use and what their licensing
| | 01:59 | code number is, right?
| | 02:01 | But you don't actually go down to
the dealership to buy a vehicle.
| | 02:05 | What you do is you buy something like a
motorcycle or a car or a truck or a boat.
| | 02:10 | These are real-world implementations
of this abstract notion of a vehicle.
| | 02:16 | Even though they may all share some of
the same characteristics, there is no
| | 02:20 | such thing as actually making a vehicle.
So in this case if the vehicle, the
| | 02:25 | class you see in the dotted line there,
is an abstract class and the classes you
| | 02:29 | see in the thick lines are real
subclasses that derive from the vehicle
| | 02:35 | subclass, you could do something like this.
| | 02:37 | I could say class Car c =
new Car. That works great.
| | 02:41 | It's a real class that
derives from the abstract class.
| | 02:44 | What I can't do is this:
| | 02:45 | I can't actually instantiate the
abstract class, because the rules of object-
| | 02:51 | oriented programming in C# is that
abstract classes have to be derived from.
| | 02:55 | So I would have to instantiate one of
the real classes, the motorcycle, the car,
| | 02:58 | the truck, the boat.
| | 02:59 | And I could add more real
classes as time goes on.
| | 03:03 | So let's just go over to the
code and see this in action.
| | 03:06 | Okay, I've got my
abstract classes example opened.
| | 03:11 | Let's go over to the snippets.
| | 03:13 | You can see I've scrolled down to my
Abstract Classes and Methods section. And I
| | 03:16 | am just going to copy these two class
definitions and I am going to paste them
| | 03:20 | in my program over here.
| | 03:23 | So now I have my abstract class, which
is myBaseClass, and in there you see I've
| | 03:28 | got my abstract method called myMethod.
| | 03:31 | And then if we scroll down a little bit,
you'll see here starting on line 13,
| | 03:34 | I have a derived class which inherits
from myBaseClass. And it overrides--again I
| | 03:42 | am using the word override here to
override the abstract member function called
| | 03:47 | myMethod--and in this case it just
takes two arguments and returns the sum of
| | 03:51 | those two arguments.
| | 03:53 | So if we go down into the Main
function, I could do something like this.
| | 03:57 | I can say myDerivedClass = new
myDerivedClass, and then I can say int result =.
| | 04:09 | Actually, I have to make it a
variable there. I can say mdc.
| | 04:15 | and then I can call myMethod right here.
And I'll just give it two numbers, 5 and 6.
| | 04:23 | And then we'll just write out the
result there, and then we'll have the program
| | 04:31 | wait for us so we can see the results.
| | 04:34 | So let's save this, and let's run it.
| | 04:36 | And you can see that the results
here is 11. Why? Because 5+6 equals 11.
| | 04:42 | So we can see that the real derived
class from the abstract class provides
| | 04:47 | implementation and actually works.
| | 04:49 | Let's comment this code out so that we
don't have to deal with any errors in it.
| | 04:54 | Okay, let's see what happens when we
take the myMethod implementation out of
| | 05:01 | the derived class. I am just going to
cut this code and save it, and now I am
| | 05:05 | going to hit F6 to build.
| | 05:07 | And you can see that we get an error.
| | 05:09 | There is little blue squiggle
underneath myDerivedClass, and if you look down
| | 05:13 | here in the error list, it says
"abstractClasses.myDerivedClass does not implement
| | 05:19 | inherited abstract member myMethod."
| | 05:22 | So you can see that because I declared
myMethod to be an abstract method, I have
| | 05:27 | to override it in my base class.
| | 05:30 | So let's undo that. Put that
back in, and the error goes away.
| | 05:34 | Let's try another little
experiment. Let's do this.
| | 05:37 | Let's say myBaseClass mbc = new myBaseClass,
and we'll save and we'll build, but another error.
| | 05:49 | What's the error this time?
| | 05:50 | It says, "Cannot create an
instance of the abstract class or
| | 05:55 | interface myBaseClass."
| | 05:57 | Abstract classes, as you can see, cannot
be instantiated by themselves, and this
| | 06:01 | is enforced by the C# compiler.
| | 06:05 | So let's go ahead and delete that code.
| | 06:09 | So abstract classes are a way of
defining abstract ideas that group together
| | 06:15 | some common properties and
functionality of real instances of that class,
| | 06:21 | but it's just abstract.
| | 06:22 | You can't actually instantiate that class.
| | 06:24 | That's a way for you to write your
programs such that you can group together the
| | 06:29 | related pieces of functionality
| | 06:30 | but force people who want to use your
classes to override them and make real
| | 06:35 | physical instances of them.
| | Collapse this transcript |
| Using sealed classes| 00:00 | The next somewhat advanced and somewhat
esoteric subject we're going to look at
| | 00:05 | in advanced C# is sealed classes and methods.
| | 00:08 | Now sealed classes and methods are
essentially the opposite of abstract classes.
| | 00:13 | Whereas abstract classes force you to
derive a subclass in order to use them,
| | 00:19 | sealed classes actually
prevent you from deriving from them.
| | 00:22 | So there is no way to make a
subclass from a class that has been sealed.
| | 00:27 | It's also possible to mark individual
methods in classes as being sealed, which
| | 00:32 | prevents them from being overwritten in
some classes. But it is far more common
| | 00:37 | to seal entire classes than methods.
| | 00:40 | And the way that you create sealed
class is by using the sealed keyword.
| | 00:44 | So if I define a class like this,
I have a public class myClass.
| | 00:47 | If I wanted to seal this class, I'd
just simply put the word sealed inside
| | 00:51 | myClass, and then at this point I
can no longer create a subclass.
| | 00:56 | So before the sealed keyword was in
there I can make my subclass off of myClass,
| | 01:00 | but now that the sealed
keyword is in there, this is an error;
| | 01:02 | I can't derive from myClass anymore.
| | 01:05 | So let's actually see this in action.
| | 01:07 | I'm actually going to go over to my
Snippets here in my SealedClasses example,
| | 01:12 | and I'm going to copy these lines of
code right here, and I'll paste them in.
| | 01:20 | So here I have my class, and let me
just take this guy out for a moment.
| | 01:25 | So I have a class called
myExampleClass and I have my subclass which derives
| | 01:31 | from myExampleClass. And if I hit F6,
you can see that everything works fine;
| | 01:36 | the Build succeeds.
| | 01:37 | Let's put the sealed
keyword back in there. Save.
| | 01:41 | Now let's try to build. Oh!
| | 01:42 | We get an error, and it says that the
subclass right here cannot derive from
| | 01:47 | sealed type myExampleClass.
| | 01:50 | So by sealing this class, I prevent any
further subclasses from being created.
| | 01:55 | You'll do this when you create classes
that you don't want people messing with.
| | 01:59 | It's not a particularly common
thing that you'll see a lot of.
| | 02:02 | The .NET Framework does this in a
couple of places where it doesn't want you
| | 02:05 | messing with things like the
Math class or other things.
| | 02:09 | Basically, if you create a class where
you want it to behave a certain way and
| | 02:13 | you don't want authors to be able to
override methods in your class, you can
| | 02:17 | create a sealed class.
| | 02:19 | So pretty quick simple example of how
you can create classes in C# that cannot
| | 02:23 | be derived from or sub-classed.
| | Collapse this transcript |
| Defining structs| 00:00 | If you're coming from a language such as
C or C++, you're probably familiar with
| | 00:05 | the notion of a struct.
| | 00:08 | If you're not, don't worry about it.
I'll explain it here.
| | 00:10 | But structs essentially are similar to
classes, but there are some important
| | 00:15 | differences that you're going to find.
| | 00:17 | First, structs don't support inheritance.
| | 00:19 | When you define a struct you define
its members and its data types and so on,
| | 00:24 | but you can't derive one struct from another.
| | 00:28 | Structs are also value types, while
classes are reference types. And if you
| | 00:32 | haven't yet watched the movie where I
explain the difference between value
| | 00:35 | types and reference types, you should probably go
watch that, because it'll make a lot more sense.
| | 00:40 | You also can't initialize the fields
of a struct inside the definition.
| | 00:44 | So, for example, when you have a member
variable inside of a struct, you can't
| | 00:49 | put a little equal sign after
it and initialize it to a value.
| | 00:52 | You have to do that outside the definition.
| | 00:54 | Structs are usually used when you
just want some small and simple data
| | 00:58 | structure to represent some piece of
information and you don't want all the
| | 01:02 | overhead of a class.
| | 01:04 | Now structs can have properties
and methods just like a class can.
| | 01:08 | You just have to remember
that they're not really classes.
| | 01:10 | You can't have inheritance.
| | 01:12 | There are all kinds of things you can't do.
| | 01:14 | So let's take a look at real example.
| | 01:15 | Suppose we wanted to define a data
type for representing a point on a
| | 01:20 | two-dimensional surface.
| | 01:21 | Well, we could do that with a class.
| | 01:23 | We'd say public class Point and we would have
an X coordinate and we would have a Y coordinate.
| | 01:27 | We could also have a constructive function.
| | 01:31 | So when someone said new point, they
could pass in a value for the X and the Y,
| | 01:36 | and that would set the X coordinate and
Y coordinate to whatever the values are.
| | 01:39 | We could also just simply declare this
to be a struct, in which case it's not a
| | 01:44 | class anymore, but everything still works.
| | 01:46 | We've got member variables, we have a
constructor function, and everything is fine.
| | 01:51 | So let's go jump over to
the code and exercise this.
| | 01:55 | Right, here I'm in my structs example,
and I've got my Snippets scrolled down to
| | 01:59 | the part on Defining Structs.
| | 02:01 | So over here in the code I'm going
to just copy these lines right here.
| | 02:05 | I am going to copy this structure definition,
copy that, and I want to paste it over here.
| | 02:13 | So now I've got my struct which defines
a point, and it's got these two private
| | 02:19 | number variables for X
coordinate and for the Y coordinate.
| | 02:23 | Then you can also see that just
with the class, I've got my constructor
| | 02:27 | function for the Point, and I've
also got a property for setting X and a
| | 02:32 | property for setting Y.
| | 02:34 | So let's go back over here and copy some code.
| | 02:37 | So the first thing I am going
to copy is this one right here.
| | 02:41 | I'll scroll down to my main function
and paste that in. And what I'm doing here
| | 02:45 | is I'm creating a point, and the
variable name is p1, and I'm creating new point
| | 02:50 | with an X coordinate and a Y
coordinate both equal to 100.
| | 02:55 | From the outside looking in, this doesn't
look any different than creating a class.
| | 02:59 | It's so happens that this is a struct.
| | 03:02 | So let's go back, get some more code.
| | 03:07 | I can also do the same thing this way.
| | 03:09 | Point p2 is s new point, and then I can
set p2.x to 50 and p2.y, and this will
| | 03:16 | invoke the getters and setters the
same way that I'd with the class.
| | 03:20 | Let's go ahead and hit F6, and you
can see that the Build succeeded.
| | 03:25 | So if we scroll back up, you notice
that pretty much the only thing is
| | 03:28 | different here is that I'm using the
keyword struct instead of using the keyword
| | 03:32 | class right there on line 8.
| | 03:34 | So then you are probably asking yourself,
okay, well, why would I want to use a
| | 03:36 | struct versus using a class?
| | 03:38 | Well, the main reason is because
you've got some small data type.
| | 03:41 | In this case, I've got a point which
only contains really two properties that I
| | 03:44 | really care about setting.
| | 03:45 | So if you got something small and you
don't want all the overhead of a class, or
| | 03:50 | you don't have to worry about things
like inheritance and overwriting stuff,
| | 03:54 | you can define a struct.
| | 03:55 | You can also use a struct when you
don't want to have to worry about things
| | 03:58 | being passed by value or passed by reference.
| | 04:02 | Again, I explained that earlier in the
section on value types versus reference types.
| | 04:07 | Structs are value types,
| | 04:08 | so you can pass these around as value
types, and the values will be copied, and
| | 04:12 | you don't have to worry about references
being changed without you knowing about it.
| | 04:15 | So anyway, that's a quick
lesson on using structs.
| | 04:18 | You'll find that in many cases if
you're define a small data structure, you
| | 04:22 | can use a struct in places where
you would normally use a class.
| | Collapse this transcript |
| Using interfaces| 00:00 | The last subject that we are going
cover in this section on building some more
| | 00:04 | advanced classes in C# is using interfaces.
| | 00:09 | Interfaces are a really
neat little feature of C#.
| | 00:12 | They essentially provide a way for
grouping a set of common behaviors in a
| | 00:18 | single place where more
than one class can use them.
| | 00:22 | Now an interface is sort of like a
class, but it provides a specification, or
| | 00:28 | you might think of it as a
contract, rather than an implementation.
| | 00:33 | You can think of interfaces as an
alternative to using abstract classes.
| | 00:40 | One of the nice things about
interfaces is that classes can implement
| | 00:44 | multiple interfaces.
| | 00:46 | Now C# doesn't have the notion of
multiple inheritance, like some other
| | 00:50 | languages do, but classes in C#
can implement multiple interfaces.
| | 00:57 | One of the best ways of thinking about
interfaces as opposed to classes is that
| | 01:00 | classes tend to be things,
whereas interfaces tend to be behaviors.
| | 01:07 | So what I can do is I can group a whole
bunch of functionality into an interface
| | 01:11 | and then that sort of becomes a contract.
| | 01:14 | If my class says that it implements
an interface, then that class has to go
| | 01:20 | ahead and providing
implementations for all of the functions that the
| | 01:23 | interface contains.
| | 01:25 | The nice thing about that is that my
class can then advertise to the world,
| | 01:30 | hey, these are the interfaces that I
implement and then in code that use my
| | 01:35 | class, the code can check my class to say, hey,
are you able to implement this kind of interface?
| | 01:41 | And if it is, then the code that's
using my interface can just say, hey, I know
| | 01:45 | that you know how to do this,
| | 01:47 | so I'm going to go ahead and call that method.
| | 01:49 | So let's take a look at how using
interfaces makes grouping behavior more easy
| | 01:55 | to understand and implement.
| | 01:56 | So let's imagine I had a few classes.
| | 01:58 | I've got class A, B, and C. Now
let's imagine further that these classes
| | 02:03 | all knew how to do something, like save
their data out to some persistent storage place.
| | 02:10 | Well, they could all just
implement a function name SaveData.
| | 02:15 | The problem is, without some interface
to enforce this, class A might call it
| | 02:20 | SaveData, class B might call it
something else, class C might call it something
| | 02:24 | else, but by grouping the notion of
saving data into an interface called
| | 02:30 | ISaveable--and interfaces don't have to
begin with a capital letter I, but it's
| | 02:35 | a nice convention that Microsoft
has come up with for interfaces;
| | 02:38 | That way when you see it in a
class definition you know that it's an
| | 02:42 | interface rather than class.
| | 02:43 | If I said, hey, I'm going to make an
interface called ISaveable and anybody who
| | 02:48 | implements the interface called
ISaveable has to have a function in their class
| | 02:52 | somewhere that's called SaveData.
| | 02:55 | So then I could do something like this.
| | 02:57 | I could say, you know what? Each one my
classes, class A, B, and C, all implement
| | 03:01 | an interface called ISaveable.
| | 03:03 | Well, that enforces
what's called a code contract.
| | 03:07 | So now everybody has to name their
function that saves the data the same
| | 03:12 | thing, because they're all
implementing from the same interface.
| | 03:16 | Now if I wanted to go a step further
and say, you know what, not only do my
| | 03:19 | objects know how to save their data,
they also know how to do something like
| | 03:23 | compress their data,
| | 03:25 | well, I could implement an interface
called IShrinkable. And inside IShrinkable,
| | 03:30 | I might have a function called CompressedData.
| | 03:34 | Now notice in the interface there's
no implementation of this function.
| | 03:38 | All that the interface says is, hey, if
you implement me, you've got to have a
| | 03:42 | function named this. And the
implementation is actually saved for the classes that
| | 03:47 | choose to implement it.
| | 03:48 | So if classes A, B, and C decided
to implement both the ISaveable and
| | 03:54 | IShrinkable interfaces--
you separate them with a comma--
| | 03:58 | well, now each one of these classes
has to have a function named SaveData, and
| | 04:03 | they all have to have a
function named CompressData as well.
| | 04:06 | Now if one of these classes decided not
to have shrinkable or saved or whatever,
| | 04:10 | they could choose not to implement
the function. But if you say that you
| | 04:14 | implement an interface, you have to
implement the members of that interface.
| | 04:19 | So let's take a look at
this working in real code.
| | 04:22 | So here in the code I've got my
UsingInterfaces example open, and I've got my
| | 04:27 | ExampleSnippets open and scrolled
down to the Interfaces section.
| | 04:31 | So let's go ahead and copy over this
line of code right here and paste
| | 04:37 | it into my program.
| | 04:39 | Now to declare an interface, you use
the word interface and then you give
| | 04:44 | your interface a name.
| | 04:45 | It's kind of like declaring a class,
although you'll notice that inside my
| | 04:48 | interface definition, I am not
providing any implementation for these methods.
| | 04:52 | I am just saying that this interface
contains two functions: one is called
| | 04:55 | SayHello, one is called SayGoodBye.
And anybody who chooses to say that
| | 04:59 | they support the ITalkative interface has
to provide implications for those two methods.
| | 05:06 | So let's go back over to the
Snippets, and let's copy over this example
| | 05:09 | class right here called myExampleClass,
and we'll paste that into my program over here.
| | 05:16 | So now I've declared a class called
myExampleClass, and it says, yes, I am using
| | 05:22 | the ITalkative interface.
| | 05:24 | So here's the constructor for
myExampleClass starting on line 16. And you'll see
| | 05:28 | that on lines 20 and lines 25, I've
got implementations for the SayHello and
| | 05:34 | SayGoodBye functions.
| | 05:36 | Let's watch what happens
really quickly if I take these out.
| | 05:39 | So I am going to cut this and
save it and then build using F6.
| | 05:44 | You will see that if I try to build
this, I'm now getting an error, why?
| | 05:47 | Because the errors say, hey, my
example class does not implement interface
| | 05:51 | members SayGoodBye and does not
implement interface member ITalkative.SayHello.
| | 05:57 | Well, that's because my class claims
to implement ITalkative, but it's not
| | 06:02 | actually doing that.
| | 06:03 | There's no implications for the
SayHello and SayGoodBye functions.
| | 06:06 | So let me just go ahead and paste those
back in and save, and then we will hit
| | 06:10 | Build again using F6, and now everything is fine.
| | 06:14 | So let's go ahead and exercise this
code, and we'll do that by copying these
| | 06:20 | lines of code right here
and we'll paste them in there.
| | 06:26 | So now in my Main function I am
declaring a variable, myEC, which is of type of
| | 06:33 | myExampleClass, and I am using the new
operator to create that object. And once
| | 06:37 | I've created that object, I can say,
all right, well, since you are a
| | 06:41 | myExampleClass and myExampleClass
implements the ITalkative interface, I know
| | 06:47 | that you've got functions
called SayHello and SayGoodBye.
| | 06:50 | So I can call each one of those.
| | 06:52 | So let's build and run.
| | 06:54 | We are going to hit F5 here, and you
can see that sure enough, when we run the
| | 06:58 | program the functions for SayHello and
SayGoodBye get executed and produce their output.
| | 07:05 | Let's go back to the Program here.
| | 07:07 | So once again, interfaces are a way of grouping
together common points of functionality.
| | 07:14 | The interfaces are not things.
| | 07:16 | You don't instantiate an interface
necessarily, although in certain esoteric
| | 07:21 | circumstances you can do that in C#, but we
are not going to get to that in this course.
| | 07:25 | It's a little bit advanced.
| | 07:26 | What you do here is you simply
create a class that says, I implement this
| | 07:30 | interface. And if you find yourself
building classes that all have similar
| | 07:34 | behavior, it's probably a sign that
you might want to make an interface that
| | 07:38 | groups that behavior into a common place
and then have each one of those classes
| | 07:43 | implement that interface.
| | 07:45 | That way you can be sure that they're
all getting the same behavior and that the
| | 07:48 | consumers of your class know that
| | 07:50 | that behavior can be counted on.
| | Collapse this transcript |
|
|
8. ExceptionsUnderstanding exceptions| 00:00 | At some point in your C# coding
experience you're going to have to learn how to
| | 00:04 | deal with error conditions.
| | 00:06 | Yes, I know, shock of all shocks.
| | 00:08 | Sometimes your code isn't going to
work the way you thought that it would, or
| | 00:11 | something is going to happen to
cause a problem in your program.
| | 00:15 | The way that we deal with that in
C# and .NET is through the use of
| | 00:19 | exceptions, and that's what we
are going to see how to use in this
| | 00:22 | particular section.
| | 00:24 | An exception is basically an error that
happens during your program's execution,
| | 00:29 | whether it's because the user put in
some data value that you weren't expecting
| | 00:34 | or the system runs out of memory
or something else that happens.
| | 00:38 | So let's take a look at an example of an
exception, and then we will learn about
| | 00:43 | how to handle exceptions in your code.
| | 00:47 | Let's imagine I have two variables, x and y.
| | 00:49 | They're both integers and I
declared them as you see here.
| | 00:53 | Then I declare another variable
called result, and I divide x by y. Well,
| | 00:57 | dividing 10 by 5, that's okay.
| | 00:59 | The result is 2. But what happens if I
set y to 0, and then I try to divide x by
| | 01:05 | y, and oh, that's a problem: I'm dividing by 0.
| | 01:09 | What happens here is the .NET
Framework raises what's called an exception.
| | 01:14 | In this case, it's a DivideByZero
exception, and we'll learn about these terms
| | 01:19 | a little bit later, but the point
is that an exception, just generically,
| | 01:23 | speaking is a problem in the code or
somewhere in the system that you have to
| | 01:29 | anticipate and handle.
| | 01:31 | So before we go any further, let's
learn about some exception terminology.
| | 01:36 | Exceptions are raised--or
using object-oriented nomenclature,
| | 01:42 | they are thrown--when an error is
encountered. When an exception happens the
| | 01:48 | normal flow of the program is
interrupted, and the control is transferred to the
| | 01:55 | nearest exception handler.
| | 01:57 | You might say that the
handler catches the exception.
| | 01:59 | So, the exception is thrown somewhere,
and then it is caught somewhere else.
| | 02:05 | Now if there is no exception handler to
process that exception and the exception
| | 02:11 | happens to be a fatal one, then the
program just terminates with an error code.
| | 02:16 | Now not all exceptions are fatal,
but some of them are and if the exception that
| | 02:20 | gets raised is fatal, then your
program is going to stop working.
| | 02:24 | Now, exceptions don't just
come from the .NET Framework.
| | 02:27 | You can build your own
exceptions and then raise them yourself.
| | 02:31 | In other words, you throw your own
exceptions using the throw instruction, and we
| | 02:36 | will see how to do that.
| | 02:38 | Let's take a look at an example of
how exceptions are handled in code.
| | 02:43 | Now there are three main keywords
you're going to have to learn about when
| | 02:47 | you're working with exceptions.
| | 02:49 | The first one is try.
| | 02:51 | Code that is placed inside the try block.
Inside those curly braces is a bunch
| | 02:57 | of code that attempts to do something.
| | 02:59 | It doesn't matter how many lines
you have in there. It could be one, it could five,
| | 03:02 | it could be 25,000; it doesn't matter.
| | 03:04 | The point is that inside that try block
you're going to do a whole bunch of code.
| | 03:08 | You're going to assign a catch block.
| | 03:12 | Now this is actually optional, but you
assign a catch block where you think an
| | 03:16 | exception might happen.
| | 03:18 | So if the code inside the try block
might cause a problem then you assign a
| | 03:22 | catch block, and this is
where exceptions are handled.
| | 03:25 | So if something goes wrong inside the
code that's inside the try then the code
| | 03:29 | that's inside the catch is going to happen.
| | 03:31 | Then last, there is finally keyword.
| | 03:34 | And this code is always run.
| | 03:36 | It doesn't matter if things
were great or things were bad,
| | 03:39 | if the code in the try section is
completely just fine or if there was a problem
| | 03:43 | and the code in the catch section had to
run, the code in the finally section is
| | 03:47 | always going to run.
| | 03:49 | So let's take a look at an example.
| | 03:50 | Suppose we had our example from earlier.
| | 03:53 | We have those two integers, one is 10,
one is 0, and we have the result.
| | 03:57 | Well, if we try to divide x by y--
in this case we got 10 divide by 0--
| | 04:01 | that's going to cause an exception,
in which case the program flow will be
| | 04:06 | transferred to the catch block.
And here we are going to just write out, hey,
| | 04:11 | look at error happened, and we do a
whole bunch of things in here. In
| | 04:14 | this case, we are writing out an error
message, but there is other code that we
| | 04:17 | could've written here to
try to handle the exception.
| | 04:19 | Maybe we could ask the user to try
putting a different value, or we can just
| | 04:22 | try something else.
| | 04:24 | The point is that the code in the catch
block is going run when the problem happens.
| | 04:28 | So let's take a look at some
real code to see how to write this.
| | 04:31 | So I am in my UsingExceptions example,
and in my Snippets you see I've scrolled
| | 04:38 | down to the Exceptions section.
| | 04:41 | So let me copy the setup code,
and we'll paste it here into main. And we'll go
| | 04:49 | back to the sample, and we'll scroll down
a little bit, and we'll take this entire
| | 04:54 | piece of try, catch, and finally,
and we will paste that in as well.
| | 05:01 | So what I've done here is I've
defined three different blocks of code:
| | 05:05 | one is called try, one is
called catch, one is called finally.
| | 05:09 | Now if I run this code in its current
state, I've got 10 being divided by 5
| | 05:15 | on line 18 right here,
and that should just be fine.
| | 05:19 | What should happen is the
Console.WriteLine for The result is, is going to be
| | 05:23 | executed, and it will show me the result.
| | 05:24 | So let's go ahead and run this and see
what happens. And you can see that the
| | 05:28 | result is 2, and you can also see that
a line is being written out there that
| | 05:31 | says, "Just proving that this code always runs."
| | 05:34 | And if we go back to the code, you'll see that
| | 05:35 | that's in the finally section down here.
| | 05:37 | Remember earlier I said that the code
in the finally section always gets run;
| | 05:41 | it doesn't matter what happens
in the try or the catch block.
| | 05:44 | So now let's change the code so that we
have an error happen. So let's do this.
| | 05:48 | We are going to change y to 0.
| | 05:51 | So now we are going to 10 divided by
0, and that's going to cause a problem.
| | 05:56 | So we are going to get to line 18.
| | 05:57 | We are going to try to divide 10 by 0,
and an exception is going to happen.
| | 06:01 | What that means that the code at line
19, this Console.WriteLine statement, is
| | 06:06 | never going to get run.
| | 06:08 | What's going to happen is the code is
going to be transferred, the program flow
| | 06:12 | is going to be interrupted, and we are
going to jump down here into this catch
| | 06:15 | block where this line of
code, the An error occurred!
| | 06:19 | Better check the code line, is going to be run.
| | 06:21 | So now let's try this.
| | 06:24 | You can see that what happened was we
tried to divide 10 by 0, which is a math
| | 06:28 | error, and you can see the Console.
WriteLine inside the catch block is writing
| | 06:33 | out An error occurred!
| | 06:34 | Better check the code. And also we can
see that the code in the finally block
| | 06:39 | always runs, because that
Console.WriteLine also got executed.
| | 06:44 | So that's a quick introduction on how
to use exceptions and as we move through
| | 06:47 | the rest of this section, we will
learn more about how to create our own
| | 06:51 | exceptions and work with
exceptions in a more advanced fashion.
| | Collapse this transcript |
| Introducing the Exception object| 00:00 | Exceptions are in fact objects, and in
fact the exception object is defined and
| | 00:06 | derived from System.Exception.
| | 00:09 | That is the base class for all the
exception objects in .NET. And the .NET
| | 00:14 | Framework actually defines a pretty
large number of exception classes.
| | 00:19 | For proof of that, let's just quickly
jump over to the MSDN web site and you can
| | 00:22 | see what I am talking about.
| | 00:24 | This is the Exception Class definition
here on msdn.microsoft.com. And if you do
| | 00:30 | a search for System.Exception or if you
go to the URL up there in the URL bar,
| | 00:34 | you'll see the exception class.
| | 00:35 | Now as we scroll down a little bit,
you'll see that just like other objects,
| | 00:40 | there are constructors.
| | 00:42 | In this case, we've got four different
constructors and there are some properties.
| | 00:47 | So these are the properties
that exceptions make available.
| | 00:50 | There's Data and HelpLink and Message,
and we'll explore some on these later on
| | 00:53 | as we through the exceptions,
but what I really want to point out is as we
| | 00:56 | scroll all the way down, you'll see that
System.Exception is the base class for a
| | 01:02 | pretty large number of
exceptions throughout .NET.
| | 01:05 | Look at how large this list is.
| | 01:07 | This isn't even a complete list.
| | 01:08 | This is a list of a lot of the
exceptions that descend directly from
| | 01:12 | System.Exception, but the one that
we're most interested in is right here,
| | 01:17 | System.ApplicationException.
| | 01:19 | This is probably one of the most common
exceptions that you will come in contact
| | 01:23 | with as a C# developer. And in fact,
I've opened that window right over here.
| | 01:28 | So this is the ApplicationException
class, and this class encapsulates all the
| | 01:33 | exceptions that are thrown when
non-fatal application errors happen.
| | 01:38 | So once again, we can scroll down.
| | 01:41 | You can see that there is Properties,
and there are all kinds of ways you can
| | 01:44 | create application exceptions.
But once again we get down to the Instance
| | 01:48 | Hierarchy or the Inheritance Hierarchy.
| | 01:50 | You can see that a lot of other
exceptions happen to descend from
| | 01:54 | ApplicationException.
And this is true throughout .NET.
| | 01:57 | You've got exceptions that are
descendents of other exceptions. And you might be
| | 02:02 | wondering, well, with all these
different types of exceptions is it possible to
| | 02:07 | write catch handlers that only
catch certain kinds of exceptions?
| | 02:12 | So to catch specific exceptions, you can
put inside parentheses for each one of
| | 02:16 | the catch handlers the kind of
exception that you're looking for.
| | 02:20 | So in the case that you see here, I've
got a try block where I'm going to try a
| | 02:25 | whole bunch of code and then I have
several catch handlers all in a row.
| | 02:29 | So I've got a catch handler for
an exception that's DivideByZero.
| | 02:32 | I've got a catch handler
for ArithmeticException.
| | 02:34 | I've got a catch handler
in case we run OutOfMemory.
| | 02:37 | There are all kinds of stuff that I can
put here, and I can put a generic catch
| | 02:41 | at the bottom of all these too that catches
exceptions that don't get caught by these.
| | 02:45 | So let's jump over to the code and
see how we can handle catching specific
| | 02:50 | types of exceptions.
| | 02:51 | So here we are in the example.
| | 02:52 | This is the ExceptionObject example.
| | 02:54 | I've got my program file open,
and down in the Snippets I scroll to the
| | 02:57 | Exception Object section.
| | 02:59 | So let's go ahead and copy the set of
code, and we'll paste that it into Main.
| | 03:04 | All right, now let's copy the try and
catch, all the way down to the finally,
| | 03:10 | okay, and we'll paste that in.
| | 03:13 | You know what? Since we already know
that the finally always runs, I am just
| | 03:17 | going to comment this line out.
| | 03:18 | We don't really need it for this example.
| | 03:20 | So let's comment it out.
| | 03:22 | All right, so this is pretty much the
same example as I showed previously.
| | 03:26 | We've got two numbers.
| | 03:27 | We've got x here which is 10.
| | 03:28 | We've got y which is 0.
| | 03:30 | We have an integer for holding the
result. And you can see here that we are
| | 03:33 | going to try to divide by zero.
| | 03:35 | The only difference from the previous
example is that here I am now catching a
| | 03:39 | DivideByZeroException, and this is an
arithmetic exception. And since I know that
| | 03:46 | it's a DivideByZeroException I can
say, hey, you tried to divide by zero.
| | 03:52 | I can also write out members of the
exception object that's passed in.
| | 03:57 | So when you catch a specific
exception, you get an argument;
| | 04:00 | in this case I've named it e,
but you can name it whatever you want to.
| | 04:03 | This will be passed into your catch
handler, and this is the exception object
| | 04:07 | that caused the exception.
| | 04:09 | So we can do things like introspect
that object and see things like what the
| | 04:13 | message that goes along with
it is and so on and so forth.
| | 04:16 | So let's save this and
let's build. Build succeeded.
| | 04:20 | All right, let's go ahead and run it and
try to divide by 0 and see what happens.
| | 04:24 | Sure enough, you can see
that You try to divide by zero.
| | 04:27 | Now that first sentence there, "Whoops!
| | 04:28 | You tried to divide by zero!"
| | 04:30 | is what I'm writing out,
and the "Attempted to divide by zero!"
| | 04:33 | string is being written out from the
message property of the exception object.
| | 04:38 | All right, let's go back to the
code, and let's try something else.
| | 04:43 | Let's copy this catch
handler and paste it down here.
| | 04:47 | Now what I am going to do
is instead of looking for a
| | 04:51 | System.DivideByZeroException,
I'm going to look for an ArithmeticException.
| | 04:55 | So I am going to hit dot and
scroll down here, and I've got an
| | 05:01 | ArithmeticException right here.
| | 05:03 | So now I'm going to save, and I am going
to build, and you can see that the build
| | 05:08 | succeeded. And what I am going to do is run this.
| | 05:13 | Now because I have the DivideByZero
handler already in place, that's the first
| | 05:17 | one it's going to jump to.
| | 05:19 | The exception is going to jump to the
first catch handler that makes the most sense.
| | 05:22 | So even though this is an
ArithmeticException, it's going to jump to the
| | 05:26 | DivideByZero version, because that's more
specific to the kind of exception I am seeing.
| | 05:31 | Let's try something else.
| | 05:33 | Let's take the ArithmeticException
and cut it and put it in front of the
| | 05:37 | DivideByZeroException.
| | 05:39 | Now you'll notice that when I do
that I get a little red squiggle on the
| | 05:41 | DivideByZeroException.
| | 05:44 | Let's see what that error
is saying. It says, "Error:
| | 05:48 | A previous catch clause already catches
all exceptions of this or of a super type."
| | 05:54 | What this basically means is because
DivideByZeroException is a subclass of the
| | 06:01 | ArithmeticException object,
this is never going to be called.
| | 06:05 | What's going to happen is a
DivideByZeroException is going be thrown, but since
| | 06:10 | it's a subclass of this guy right here,
this catch block is going to catch all
| | 06:15 | the math problems that might come up,
including DivideByZero. And since it
| | 06:20 | occurs first, this code will never get executed.
| | 06:23 | So the C# compiler is catching that
situation for me and saying, hey, you sure
| | 06:28 | you want to do this?
| | 06:29 | Why would you put in a catch handler that's
never going to be called? So let's do this.
| | 06:33 | Let's take that WriteLine out, cut that line.
| | 06:36 | Let's put that in there instead.
Let's see what the message is for
| | 06:39 | ArithmeticException, and let's just
take out the DivideByZeroException.
| | 06:43 | So now I am catching the more general case.
| | 06:46 | I'm catching the
ArithmeticException now, not just specifically the
| | 06:49 | DivideByZero, although
DivideByZero is an ArithmeticException.
| | 06:54 | So let's run this, and you can see that
we're getting the same message in this case.
| | 06:58 | So even though we got an
ArithmeticException, it knows specifically what
| | 07:01 | happened, and the message in this
case is an "Attempted to divide by zero."
| | 07:05 | So by using the ExceptionObject, your
code can look for and catch specific
| | 07:10 | exceptions. And if you don't want to
catch a specific exception, you can use the
| | 07:15 | catch handler. That just catches
any exception that comes its way.
| | 07:19 | This is way for your code to be on the
lookout for specific kinds of exceptions
| | 07:23 | so that it can take corrective action
and try to prevent the user from having a
| | 07:26 | bad experience while using a program.
| | Collapse this transcript |
| Creating your own exceptions| 00:00 | Now I mentioned earlier that
exceptions don't just simply come from .NET;
| | 00:04 | you can create your own custom
exceptions--and in this movie we are going to
| | 00:08 | see how to do that.
| | 00:09 | Essentially, by sub-classing the
exception object from the system namespace you
| | 00:15 | can create your own exceptions.
| | 00:17 | And then when you're ready to raise an
exception, you use the throw instruction.
| | 00:22 | So for example, you can do things like
throw a new System.Exception, or you can
| | 00:27 | throw a new MyCustomException.
| | 00:28 | You have to have the new in there
because you've got to create the exception object
| | 00:33 | that you are going to throw, and then
the throw keyword will cause the exception
| | 00:36 | to be thrown, and then the catch
mechanism will go into effect.
| | 00:41 | So let's go over to some live code to
see how we define our own exceptions and
| | 00:45 | then throw and catch them.
| | 00:47 | So I have my Custom Exceptions
example here, and here is my Snippets. I've
| | 00:51 | scrolled down so they are
creating exceptions section.
| | 00:54 | What I am going to first is just scroll
down here and I am going to copy some of
| | 00:58 | the setup code, copy this, and I am
going to paste this in my program. And then
| | 01:05 | I'm going to go back and I am going to
ignore the catch section for a moment;
| | 01:08 | I'm just going to get the
finally section, put that in here.
| | 01:12 | Now one of the first things you realize
is that you don't actually need to have
| | 01:16 | a catch section at all.
| | 01:17 | You can just have try
and finally if you want to.
| | 01:20 | So what I've got here is some code.
I've got a string variable called the name,
| | 01:24 | and then in my try block I've
got a function called getName.
| | 01:28 | Well, actually, I haven't defined it yet.
That's why there is a little squiggle there.
| | 01:31 | But the getName function is going to
ask the user to input a name, and it's
| | 01:35 | going to return it in the form of a
string. And then I've got code on line 17
| | 01:40 | which simply writes out "Hello" and then
whatever the name that you put in. And
| | 01:44 | then in the finally block, which remember always
runs, we have a string that says, "Have a nice day!"
| | 01:48 | So let's go back to the snippets and
get that getName function. And what I am
| | 01:53 | going to do is get this right here,
copy that, and I am going to paste that
| | 01:59 | function in right up here. And for the moment
I am going to just take this part out of it.
| | 02:05 | So what we are going to do in getName
is use the Console.ReadLine function to
| | 02:10 | read a string, and then we
are going to return that string.
| | 02:14 | So let's go ahead and run the code
that we have and see how well it works.
| | 02:18 | So I am going to just build. It ran.
| | 02:21 | So now it's waiting for me to enter a name,
and I am just going to type in the name scott.
| | 02:26 | It says, "Hello scott. Have a nice day!"
| | 02:27 | Great, okay everything is working fine.
| | 02:29 | Let's suppose we wanted to catch a certain
name though and have that cause an exception.
| | 02:35 | So let's go back to the getName
function, and what we are going to do is we are
| | 02:41 | going to say you know, if the string
that was entered equals Joe, we're not going
| | 02:45 | to allow the word Joe to be put in.
| | 02:47 | So we are going to throw an
exception called the NoJoesException.
| | 02:50 | Now we have to define the
NoJoesException, which you see right here on line 14.
| | 02:56 | So let's go back to the Snippets and scroll up.
| | 03:00 | Here we have our
definition for the NoJoesException.
| | 03:03 | Let's copy that, and we'll
paste it in. And it's a class,
| | 03:07 | so I am going to paste it
outside my program class.
| | 03:10 | So you can see on line 8, I've got
a definition here for public class
| | 03:14 | NoJoesException, and there's the colon,
which means it inherits from the exception
| | 03:19 | class, which is contained
in the system namespace.
| | 03:22 | And remember, since I'm using the system
namespace up here, I don't have to write
| | 03:26 | out System.Exception.
| | 03:27 | I can just use the word exception here.
| | 03:29 | So inside my NoJoesException, I've got
my constructor, and my constructor is a
| | 03:34 | public NoJoesException constructor.
And what I'm doing here is I'm calling the
| | 03:40 | base exception constructor with a string.
| | 03:44 | So before I go any further, let's just
jump back over to the MSDN documentation
| | 03:48 | to see what the system exception looks like.
| | 03:52 | So here we are, in the
documentation for the exception class.
| | 03:55 | Let's scroll down, and you can see
that there are four different ways I can
| | 03:59 | construct an exception class.
| | 04:02 | There is a constructor that takes no arguments.
| | 04:05 | There is a constructor that takes an
argument that's a string, and it says
| | 04:08 | here, "Initializes a new instance of the
exception class where they specified error message."
| | 04:14 | Well, that sounds pretty much like the
one I want. Let's just make sure.
| | 04:18 | Next one is exception with
serialization and info and streaming context,
| | 04:22 | whatever that is,
because it's obviously wrong.
| | 04:24 | And there's the exception here with a
specified error message and a reference to
| | 04:28 | the inner exception. Okay, that's pretty
advanced. I am not going to use that one.
| | 04:32 | Looks like number two is the one I want.
| | 04:34 | So I have to initialize a new
instance of the exception class with the
| | 04:37 | specified error message.
| | 04:39 | Okay, that sounds great.
Let's go back to the code.
| | 04:41 | Well, the way that I do that in C#--
| | 04:43 | well, there is a couple of ways I can do it.
| | 04:45 | First, I am just going to call the
base-level constructor with the string here.
| | 04:49 | Now you might be wondering, why am I not
just simply inside my constructor doing
| | 04:53 | something like this?
| | 04:54 | this.Message = No Joes allowed.
| | 05:00 | I am going to save that and I am
going to build. Wait, we've got an error.
| | 05:04 | It says, "Property or indexer System.Exception.
Message cannot be assigned to--it is read only."
| | 05:10 | Oh! So I can't actually make an assignment to that.
| | 05:13 | Looks like the only way to do it in
this case is through the constructor. Okay,
| | 05:17 | well, I guess I won't do that then.
| | 05:20 | So it looks like this base
method is the only way to do that.
| | 05:22 | So I'm passing in an error message to
initialize the exception with "We don't
| | 05:25 | allow No Joes in here!"
| | 05:27 | However, I can give the user some help .
And there is a field, or a property in
| | 05:33 | this case, called HelpLink. Again let's just
jump over to the documentation very quick.
| | 05:38 | So if we scroll down, you'll see
there is a property called HelpLink, and it
| | 05:42 | says, "Gets or sets a link to the help file
associated with this exception." Oh cool!
| | 05:48 | Okay, so I can tell the user what to do
in case an exception like this happens.
| | 05:53 | Let's go back to the code.
| | 05:55 | So what I am going to do is
initialize my HelpLink here on line 13 to be a
| | 05:59 | link to my web site.
| | 06:01 | So back down here in the program--let me
close this error window so we have more space--
| | 06:06 | you can see that when we get the input
from the user, we are going to see if the
| | 06:11 | string is equal to Joe and if it is, we
are going to throw the NoJoesException.
| | 06:16 | Now there's one more thing we have to do:
| | 06:18 | we have to implement the catch block
for the NoJoesException. So let's go back
| | 06:21 | to the code, and down here in the
Snippets we've got my catch handler.
| | 06:26 | I am going to copy that,
| | 06:28 | go back over here, and in between try and
the finally, I am going to paste that in.
| | 06:31 | So you can see here what I am doing
is I'm going to catch specifically a
| | 06:36 | NoJoesException, and I've named the variable nje.
| | 06:40 | So what I am going to do is write out
the message, which is what I initialized
| | 06:44 | it with up in the constructor, and then
another line I am going to write out "For
| | 06:48 | help, visit," and then I am going to write out
the HelpLink field that's in my NoJoesException.
| | 06:52 | All right, it looks like everything is ready to go.
| | 06:57 | Let's hit F6. Okay, the build succeeded.
| | 06:59 | Let's hit F5 to run it.
| | 07:01 | All right, so I am going to type in
"scott," "Hello scott Have a nice day!"
| | 07:06 | That seems to work okay.
| | 07:07 | Let's try it one more time with Joe. Oh!
| | 07:10 | Now, we get an error. It says "We don't
allow no Joes in here! For help, visit:"
| | 07:14 | and then use the help link that I
put into my help message for the user.
| | 07:19 | And of course in the finally
block it says, "Have a nice day!"
| | 07:22 | All right, so this is how you can
create your own exceptions, throw your own
| | 07:26 | exceptions, and use some of the fields
provided by the base system exception
| | 07:31 | object to give your users some help
and some detailed messages for when
| | 07:34 | those errors occur.
| | Collapse this transcript |
| Re-throwing exceptions| 00:00 | The last subject that we're going
to examine in the area of exceptions is
| | 00:05 | that of rethrowing exceptions. And what
that means is when an exception happens
| | 00:10 | inside your catch handler, you can do
some processing, but if you handle the
| | 00:15 | exception, the exception
pretty much stops with you.
| | 00:18 | You can keep it going by throwing it again,
or hence the term 'rethrowing' the exception.
| | 00:24 | Now, why would you want to do this?
| | 00:25 | Let's take a look at an example,
and hopefully that will make it a little bit more clear.
| | 00:29 | So here in my RethrowingExceptions
example what I am going to do is go to my
| | 00:32 | Snippets and I am going to
copy some code in over here.
| | 00:37 | So first, I am going to start with
these lines down here, and I am going to copy
| | 00:41 | those and paste them into my Main function.
| | 00:46 | So I've got some code that calls a
function called DoSomeMath, and it catches an
| | 00:53 | ArithmeticException and
writes out a message that says hey!
| | 00:56 | Look, something went wrong in there.
| | 00:58 | You might want to be careful, or
something like that. All right!
| | 01:00 | Now let's go back to the Snippets.
| | 01:04 | Let's copy the DoSomeMath function.
All right and that's going to go up here.
| | 01:11 | So starting here on line 10 I've got
my DoSomeMath function, and this is the
| | 01:16 | example that we've been
working with up until now.
| | 01:18 | So what DoSomeMath is going to do is
the same thing we've seen up until now,
| | 01:22 | which is try to divide by 0.
| | 01:24 | So here I've got my two variables on line 12.
| | 01:26 | I've got my result on line 13.
| | 01:27 | Here on line 15 I've got my try block,
and I am going to try to divide 10 by 0.
| | 01:33 | Now, of course, what's going to happen
is that's going to cause an exception.
| | 01:37 | So the catch handler will execute here,
and I will write out something like hey!
| | 01:43 | You know, there is an error in DoSomeMath.
| | 01:45 | But I don't want the
exception to just die here with me;
| | 01:48 | I want the exception to continue on and
have other exception handlers do their
| | 01:54 | thing, because there might be some
additional work that needs to be done.
| | 01:58 | So inside my catch handler, I am
going to throw a new ArithmeticException.
| | 02:04 | Now, if I want to just rethrow the
same exception, I wouldn't do this.
| | 02:07 | What I would do is I would just simply do this;
| | 02:09 | I would take out this new and just say throw.
| | 02:12 | What that means is, take the same
exception that I am currently handling and
| | 02:16 | just rethrow it again. And that would
be the same exception objects. Things
| | 02:21 | would just continue on as they were,
and my catch handler would just be one and
| | 02:25 | a line of catch handlers.
| | 02:27 | But what I am going to do here is--let
me put that code back in--I am actually
| | 02:30 | going to throw an entirely new
exception called an ArithmeticException, because
| | 02:35 | remember, what I am catching
here is a divide-by-0 exception.
| | 02:38 | So let's go ahead and save,
and I am going to run this.
| | 02:41 | So you can see that what happened
here is both catch handlers executed.
| | 02:46 | There's the catch handler inside the
DoSomeMath function, and then there was the
| | 02:51 | catch handler that was in my Main program.
| | 02:54 | So let's go back and take a look.
| | 02:57 | You can see that this catch handler
executed and this catch handler executed.
| | 03:02 | If I didn't have this line of code in
here--and let me just comment it out, now
| | 03:07 | let's try rerunning it again--
| | 03:09 | you can see that in that case,
only my catch handler executed.
| | 03:12 | So the other catch handler doesn't get
a chance to run. The exception just gets
| | 03:17 | handled and dies in the DoSomeMath
function and doesn't get a chance to continue on.
| | 03:22 | So by rethrowing the exception, or in
this case throwing the new one, we give the
| | 03:27 | other exception handler a chance to do its stuff.
| | 03:30 | So why would you do this?
| | 03:31 | Well, suppose you've got an exception
handler whose job is to just log out
| | 03:36 | whenever a particular exception happens.
| | 03:39 | You don't want that catch handler
to be the be-all and the end-all.
| | 03:42 | You just want to insert it in the
handling process so that that way your log
| | 03:46 | file shows that an exception happened.
And then once that exception handler is
| | 03:49 | done logging out whatever information it
needs to log out, it can continue on and
| | 03:54 | rethrow that exception so that the
other real exception handlers in the process
| | 03:59 | somewhere get a chance to do their work.
| | 04:01 | So let's take a look at what happens
when I take out the new ArithmeticException.
| | 04:07 | And I am not going to change
the catch section right here.
| | 04:10 | I am just going to leave it alone.
| | 04:11 | So I am going to run it, and you can see
that now both catch handlers are being
| | 04:15 | handled again. And because a divide by
0 is an ArithmeticException, the other
| | 04:21 | exception handler is being executed.
| | 04:23 | So this is a really great way to segment
out your catch handlers so that each one
| | 04:28 | does its own little piece of work and
they don't interfere with each other and
| | 04:32 | they are able to pass the exception on
down the chain so that all the exception
| | 04:36 | handlers have the chance to do
whatever it is that they need to do.
| | 04:39 | Just make sure that the last exception
handler in the line is the last exception
| | 04:43 | handler in the line.
| | 04:44 | It doesn't pass the
error up through to the user.
| | 04:47 | At some point, the error needs to be
handled and not shown to the user--well, at
| | 04:51 | least in most cases.
| | 04:52 | So you're going to want to make sure
that at least one of your catch handlers is
| | 04:55 | where the exception eventually stops.
| | Collapse this transcript |
|
|
9. File ManagementIntroducing streams and files| 00:00 | We've reached the point now where we've
seen enough C# to start doing some real
| | 00:04 | stuff, and one of the more common
"real stuffs" that you'll probably do when
| | 00:09 | working with C# is moving
information into and out of files. And the .NET
| | 00:14 | Framework provides some really great
utilities for working with files and
| | 00:17 | information in files, and that's what
we're going to cover in this section.
| | 00:21 | We're going to start off with an
introduction to streams and files.
| | 00:26 | So let's start talking about that right off.
| | 00:28 | When you want to move the data into or
out of a file or across the network or
| | 00:32 | over the Internet or some block of
memory or some other location, the data has
| | 00:38 | to be what's called streamed.
| | 00:40 | You can think of a stream as an
analogue to its real-world counterpart.
| | 00:44 | Think of water moving between two
bodies of water in the form of a stream
| | 00:50 | or river or whatever.
| | 00:51 | In this case, however, the stream data
is a bunch of 1s and 0s that represent
| | 00:57 | the information of a file, and the body
of water is called the backing store.
| | 01:03 | Now the backing store can be
anything. It can be a file.
| | 01:06 | It can be someplace on the network.
| | 01:10 | It can be some place out over the Internet;
| | 01:12 | it doesn't really matter what it is.
| | 01:13 | The point is the backing store is where
the information goes to or comes from.
| | 01:19 | Streams have certain properties:
| | 01:20 | they can be readable, they can
be writable, or they can be both.
| | 01:25 | Streams can also be what's called seekable.
| | 01:28 | In other words, some kinds of streams
have this notion where there is a position
| | 01:32 | that you can look at and modify.
| | 01:35 | Sometimes this is called a random access stream.
| | 01:38 | Streams descend from the
System.IO.Stream abstract base class.
| | 01:45 | Now we're not going to work too deeply
with streams themselves in this section;
| | 01:49 | we're going to stick to the higher-level
classes and utilities for working with files.
| | 01:53 | But it's important to have an
understanding of what they are, and it's useful to
| | 01:57 | have this background so that later on,
when you want to go and work a little bit
| | 02:00 | more deeply with files, you'll
understand what a stream is.
| | 02:03 | So at the top, we have the stream
class and again, this is an abstract
| | 02:06 | base class. And we looked at abstract base
classes a little bit earlier in the course;
| | 02:10 | if you haven't watched that
section, you should go do that now.
| | 02:13 | This is a class that forces you to create a
subclass in order to provide an implementation.
| | 02:19 | So these stream abstract base class
provides a whole bunch of abstract, or
| | 02:23 | theoretical, things that streams need to
be able to do, and then the real stream
| | 02:27 | classes you work with descend
from streams, such as the FileStream.
| | 02:31 | This is a class for working
with physical files on the disk.
| | 02:35 | There is also the MemoryStream,
which is locations located somewhere in
| | 02:39 | the computer's memory.
| | 02:40 | There is the NetworkStream.
| | 02:42 | This is used to move
information across the network.
| | 02:45 | So actually, let's take a quick look
over at MSDN so you can see what the stream
| | 02:49 | base class looks like.
| | 02:50 | All right, so this is the stream class
documentation here on msdn.microsoft.com.
| | 02:55 | You can see the URL up there in the browser
if you want to go and look at it for yourself.
| | 03:00 | The stream class--let's
just scroll through this--
| | 03:02 | you can see that there's a
constructor which makes a new stream, and there
| | 03:06 | are some properties, things like
CanRead, and CanSeek, CanTimeout, CanWrite,
| | 03:10 | that kind of thing.
| | 03:11 | And if we scroll down a little
bit further, there are methods,
| | 03:14 | methods for reading and writing information,
for copying information, so on and so forth.
| | 03:18 | These are all the base-level
functionality features that a stream has to
| | 03:23 | provide to its users.
| | 03:24 | Now remember, this is an abstract base class, so
you won't actually instantiate a stream class;
| | 03:30 | what you'll use is one of the
subclasses. And if you continue scroll down,
| | 03:34 | you'll see that underneath the System IO
Stream, there is a whole bunch of other streams.
| | 03:38 | There's BufferedStream, there is
FileStream, there is MemoryStream, and here is
| | 03:42 | the NetworkStream I talked about earlier.
| | 03:43 | These are the actual stream
classes that you will use.
| | 03:46 | But we're not going to cover that right now;
| | 03:48 | what I'm going to do is talk about the
file and directory higher-level classes
| | 03:52 | that we're going to use in this section.
| | 03:55 | .NET provides a collection of
useful classes for working with files and
| | 04:00 | directories, so let's go over those right now.
| | 04:03 | One is called the File class, and this
provides a very simplified high-level set
| | 04:07 | of functions for working with files.
| | 04:09 | In fact, this is mostly a static class
where you call the methods of this class
| | 04:14 | using the file.notation. And if you
haven't watched the section on classes, you
| | 04:19 | should go do that to
understand what a static class is.
| | 04:22 | So file is probably the highest
level example of working with files.
| | 04:26 | The next one down is the FileInfo class.
| | 04:28 | This provides more detailed lower-level
functions that provide a little bit more
| | 04:32 | control over working with files.
| | 04:34 | Then there is the FileStream class, which I
briefly talked about just a few moments ago.
| | 04:38 | This exposes a stream object around
a file, which provides very detailed
| | 04:42 | control over how information gets
written to and read from the file.
| | 04:47 | For directories, there is a sirectory
class and this is sort of the analogue to
| | 04:51 | the file class. It provides very simple
high-level functions for working with
| | 04:55 | directories, or folders. And then
there's the DirectoryInfo class which provides
| | 04:59 | some more detailed lower-level
functions that provide a bit more control over
| | 05:04 | working with directories.
| | 05:05 | So we're going to use some of these
classes in the rest of the section to work
| | 05:08 | with files and directories.
| | Collapse this transcript |
| Working with existing files| 00:00 | Let's begin with something simple.
| | 00:01 | We are going to see how to
work with existing files.
| | 00:04 | Now, the file class provides some
features for working with files. And as I
| | 00:08 | mentioned earlier, most of the
methods in this class are static.
| | 00:11 | You call them directly on the file
object. And if you're not familiar with
| | 00:15 | static classes, you should go back and
watch the section on classes to find out
| | 00:19 | what a static class is.
| | 00:21 | So the file object provides
some really simple functions.
| | 00:24 | I am going to go over some of them here,
not all of them, because it's quite a few.
| | 00:27 | But, for example, there is an exists
method that checks to see if a file at a
| | 00:31 | given path exists or not and if a
file does not exist, you can call a method
| | 00:36 | called create, which, surprisingly,
creates the file at the specified path.
| | 00:40 | There are also functions for
copying and moving and deleting files.
| | 00:45 | There is File.Copy, which
copies a file to another location.
| | 00:48 | There is a Move function, which as the
name indicates, moves a file, and there is a
| | 00:53 | delete function which
deletes a file at a specified path.
| | 00:57 | So let's jump over to the code and exercise
some of these functions and see how they work.
| | 01:02 | Okay, so I'm here in my existing
project with my program file open, and here is
| | 01:09 | my Snippets. And I've scrolled
down to the Existing Files section.
| | 01:13 | So let's begin by just checking to
see if a file exists. And what I am going
| | 01:18 | to do is use a couple of other
utilities to get a path to a special location
| | 01:24 | here on my computer.
| | 01:25 | So we're going be working with files in
the My Documents folder, and I am going
| | 01:29 | to copy these first few lines right here.
| | 01:34 | So let's take a quick review of these
lines of code before we do anything else.
| | 01:38 | So the first few lines, I have a
Boolean variable called fileExists and I
| | 01:42 | initialize it to false because we are
going to assume that the file doesn't exist.
| | 01:46 | Then we need to build up a file path,
and the path just basically specifies where
| | 01:51 | on the computer the file exists or not.
| | 01:54 | So here I am going to say I have string
called the path, and I am going to use a
| | 01:59 | special .NET class called the environment class.
| | 02:03 | The environment class gives me
some utilities for working with the
| | 02:06 | Windows environment.
| | 02:08 | So I am going to ask the
environment to get me a folder path, and the
| | 02:11 | GetFolderPath function can take
a couple of different arguments.
| | 02:14 | I'm going to use the
Environment.SpecialFolder.MyDocuments property, and this
| | 02:20 | will get me a path to the My
Documents folder on this computer.
| | 02:25 | Now I could have just hard coded this by
typing in C:\users\Joe Marini, so on and so forth.
| | 02:33 | That's really not a very good practice.
| | 02:35 | You don't want to hard code things into
your applications if you can avoid it.
| | 02:39 | And windows, and in this case .NET, provides
a bunch of utilities for working with
| | 02:43 | special document folders. Not just My
Documents, but things like the temporary
| | 02:47 | directory and the trash or the
recycle bin, that kind of thing.
| | 02:51 | So I am using this environment class right
here to get the path to the My Documents folder.
| | 02:56 | So once I have the path to the My
Documents folder, I'm then going to add on to
| | 03:03 | the end this string right here, which
is testfile.txt. And recall I put the @
| | 03:10 | sign at the front of the string to prevent this
\t here from being treated as a tab character.
| | 03:17 | I want the backlash to be
treated as a path separator.
| | 03:21 | So at the end of all this I'll have a
full path to a file named testfile.txt.
| | 03:26 | All right, let's go bring
up my, My Documents folder, so
| | 03:29 | you can see what's in it.
| | 03:31 | Okay this is the My Documents folder,
and you can see that right now there is
| | 03:34 | no file named test file.txt in here, so
we're going to create it if it doesn't exist.
| | 03:39 | Let's go back to code.
| | 03:41 | We start off by using the
File.Exists function here on line 17.
| | 03:46 | So we call File.Exists. That returns a
Boolean result indicating whether the file
| | 03:50 | exists. And then I have an if
statement and my if statement says if the file
| | 03:55 | exists. Then just write out to
the console that the file exists.
| | 03:59 | Otherwise write out that the file does
not exist and we are going to create it.
| | 04:02 | Then we call the File.Create function with
the path, and this will create the file for us.
| | 04:08 | So let's go ahead and see what
happens when we build and run this.
| | 04:13 | The code compiles and runs, and you can
see that we're getting a message out to
| | 04:16 | the console that says, "The
file does not exist. creating it."
| | 04:19 | So let's go back for our My
Documents folder, and you can see now that the
| | 04:23 | test file has been created. And in this
case, I am hiding known file extensions, so
| | 04:29 | you don't see that.txt on
the end there, but it is there.
| | 04:32 | Okay, so test file has now been created.
Let's go back and do some more work with it.
| | 04:37 | Let's go back to Snippets, and we'll copy
this over, copy, and we'll paste this in.
| | 04:52 | Okay, so I am going to comment out
these last two lines, just for a moment.
| | 04:57 | So once we've determined that the
file exists, we can then get some
| | 05:00 | information about it.
| | 05:01 | In this particular section of code here
I'm saying if the file exists then let's
| | 05:06 | figure out when it was created. And we
are going to use the Files.GetCreationTime
| | 05:11 | method and the GetLastAccessTime method
for the file, and we passed in the file
| | 05:17 | path both times to get
information about the file.
| | 05:20 | And this will tell us when the file was
created and when it was last accessed.
| | 05:23 | Okay, so now when I run the
program again the file already exists,
| | 05:28 | so this part of the If statement should
execute and we shouldn't have to re-create it.
| | 05:32 | So I am going to save, and I am going to run, and sure
| | 05:36 | enough, you can see that I am
getting the message, "The file exists."
| | 05:39 | So we didn't have to re-create it,
and you can see it was created on such and
| | 05:42 | such a date at such and such a time,
and it was last accessed on such and such a
| | 05:46 | date and such and such a time.
| | 05:48 | Let's finish up our exercise by
moving the file to a new location.
| | 05:51 | So I am going to hit return and exit on that.
| | 05:53 | Now I am going to uncomment these last
two lines here, and we are going to move
| | 05:57 | the file somewhere else
using the File.Move function.
| | 06:01 | And what we are going to do is move the
file from its existing path--that's the
| | 06:05 | first argument--to the path, but we
are just going to give it a new name.
| | 06:09 | So it's going to stay in the same folder,
but it's going to be renamed to newfile.txt.
| | 06:14 | So we are going to save, and we are
going to run, and you can see that we are
| | 06:20 | still getting the original message that it
exists and the creation and access times.
| | 06:24 | And now we are moving the file.
| | 06:26 | So let's go back to the My Documents folder,
and you can see, that test file is no longer there.
| | 06:31 | It is now called newfile.
| | 06:33 | So you can use these functions to
operate on files that are existing or create
| | 06:37 | new ones on your file system.
| | 06:40 | And if you feel like getting a little
bit more advanced, go take a look at the
| | 06:42 | file class. There is a whole bunch of
other useful methods in there that you can
| | 06:46 | experiment with for working with existing files.
| | Collapse this transcript |
| Working with directory and disk information| 00:00 | As you might have guessed, just as
there are ways for working with existing
| | 00:03 | files, there are ways to work with
existing directories. And whether you called
| | 00:07 | them directories or folders, it
doesn't really matter; they're the same thing.
| | 00:11 | But in the .NET Framework the
class is called a directory.
| | 00:15 | Now working with directories is pretty
similar to working with files, except that
| | 00:20 | directories can also contain other
files and directories, whereas files just
| | 00:25 | contain information.
| | 00:26 | But there are classes for
working with directories.
| | 00:28 | There is of course the
Directory.Exists function which tells you whether a
| | 00:32 | directory exist or not.
| | 00:33 | You can also create and delete
directories the same way you can with files.
| | 00:38 | You can figure out what the
current directory is for the application.
| | 00:41 | This is the directory that the
application is currently looking at, what it
| | 00:45 | thinks is the current one, where
information will be written to or read from.
| | 00:50 | And just like in the other directories,
they contain other things. You can get the
| | 00:54 | files and get the directories that are
contained within a directory. And just
| | 00:58 | like files, you can move directories around.
| | 01:00 | So let's jump over to the code and
exercise some of these functions so we
| | 01:04 | can see how they work.
| | 01:05 | Here I am in my ExistingDir project,
and once again I've got my Snippets file open.
| | 01:10 | So I've scrolled it down to the
Existing Directories part, and I'm going to just
| | 01:15 | copy these first few lines right here.
| | 01:21 | So this example, so far, isn't too different
than the example we saw for the files case.
| | 01:27 | Right here at the top, I've got the
string variable called the path, which I'm
| | 01:31 | using to figure out where
the MyDocuments folder is.
| | 01:35 | Once again, I'm using the Special
Environment class, and I'm calling the
| | 01:40 | GetFolderPath, which will tell me where
the MyDocuments folder is. And just to
| | 01:46 | show you there are lots of
features on here, I'm going to just hit little
| | 01:49 | dot here on special folder, and you can
see there is a whole bunch of special
| | 01:53 | folder I can get paths to.
| | 01:54 | There is the Admintools.
| | 01:55 | There is CommonDocuments.
| | 01:56 | There's things like Music and Pictures.
| | 01:59 | There's the Startup directory.
| | 02:01 | There is the Desktop.
| | 02:02 | There is a whole bunch of special
paths that you can get access to.
| | 02:06 | I'm just going to go ahead
and leave it as MyDocuments.
| | 02:08 | This will get me the path
to the MyDocuments folder.
| | 02:11 | Then we're going to call the
Directory.Exists function right here on line 1,6 to
| | 02:16 | see if that directory actually exists or not.
| | 02:19 | Since it's the MyDocuments folder,
I'm pretty sure it's going to exist.
| | 02:24 | So we have an if clause here that says
if the directory exists then write out to
| | 02:29 | the console that it does;
otherwise write out that it doesn't.
| | 02:32 | So this is a pretty good place to start.
| | 02:34 | Just go ahead and save and
run this in its current form.
| | 02:38 | And you can see that the result is that
the directory exists. So far so good.
| | 02:42 | Let's continue on.
| | 02:44 | Let's go back to the
Snippets and get some more code.
| | 02:47 | What we're going to do now is use the
GetFiles function on the directory class
| | 02:53 | to write out the names of the
files that are in that directory.
| | 02:56 | So we are going to copy, and we
are going to paste that down here.
| | 03:05 | So let's save, and let's take look.
| | 03:07 | So the GetFiles function that you see
here on line 24 returns a string array,
| | 03:13 | which is why I'm declaring this string
array variable called files, which will
| | 03:18 | hold the results of the GetFiles
function. And I pass in the path which is now
| | 03:24 | the MyDocuments folder.
| | 03:25 | Then below that I'm using our newly
discovered foreach loop construct, and so I'm
| | 03:32 | going to loop over all the
strings in that files array.
| | 03:35 | So for each string--and I'm going to call
each one of that S--that's in the files array,
| | 03:40 | I'm going to write out to the console
I found a file plus whatever the file
| | 03:44 | name is right here.
| | 03:46 | Now I could use the Formatting
String function, but I just chose not to
| | 03:49 | for simplicity here.
| | 03:50 | So let's go ahead and build this, and we
can see the build succeeded, and let's run it.
| | 03:54 | It looks like we found a
couple of files in there.
| | 03:57 | We've got a couple of contents of the directory,
| | 04:00 | so that seems to be working.
| | 04:02 | Let's hit Return and go back
to the code. Let's move on.
| | 04:08 | Now we are going to do a
little bit of extra credit.
| | 04:10 | It turns out that there is a class
called Drive Info, and I'm going to leave that
| | 04:15 | up to you as an exercise to go onto
MSDN and look up this class to see what it
| | 04:20 | does. But I'm just going to do a really
quick simple experiment here. I want
| | 04:23 | to copy the code, and then
we'll explain what it does.
| | 04:28 | So just like you can work with files
and directories, you can also work with
| | 04:33 | disks or other storage devices
that are attached to your computer.
| | 04:38 | So what we're going to do here is get
information about each one of the disk
| | 04:41 | drives on the computer, as long as it is a
fixed drive. You'll notice that there are
| | 04:47 | different kinds of drives when you
look up information about this class.
| | 04:51 | There are things like removable
drives and so on and so forth.
| | 04:53 | So what we're going to do is write out
that we're getting the drive information.
| | 04:57 | You can see that up here on line 32.
| | 04:58 | Then we're going to call here on
line 33 the GetDrives function, and as a
| | 05:05 | shorthand we're just going to
loop this inside a foreach loop.
| | 05:08 | So we're going to get each DriveInfo,
because the GetDrives function comes back
| | 05:14 | with an array of DriveInfo structures.
| | 05:17 | So we're going to say for each
DriveInfo D which is in the array that comes
| | 05:22 | back from GetDrives,
| | 05:24 | we're going to execute the code in
this loop. And we're going to ask the
| | 05:27 | DriveInfo if the DriveType is
equal to the DriveType.Fixed.
| | 05:33 | Like I said earlier, there
are all kinds of examples here.
| | 05:36 | If I hit the period, you'll see that
there is CDRom and Fixed and Network and
| | 05:39 | so on and so forth.
| | 05:40 | So we're just going to stick with
Fixed, and we're going to write out the
| | 05:43 | information about each one of the fixed drives.
| | 05:44 | We'll write out its name, how much free
space it has, what type it is, and so on.
| | 05:49 | So let's go ahead and save. Let's build.
| | 05:51 | It works, and now let's run it.
| | 05:55 | You can see now that we're writing
out some information about not just the
| | 05:58 | files, but the drive information.
| | 05:59 | So we seem to have too fixed drives:
one is called C:, one is called D:.
| | 06:04 | They're both fixed and they both have a
lot of free space. That's how many bytes
| | 06:08 | are free in each one.
| | 06:09 | That's a quick example for
working with directories and drives.
| | 06:12 | Now let's move on and look
at some more file information.
| | Collapse this transcript |
| Using the Path class| 00:00 | One of the things that you're going to
find yourself doing over and over again
| | 00:03 | as you work with files and
directories and so on is that there's a lot of
| | 00:07 | information contained in paths,
and you'll find yourself having to parse out
| | 00:12 | paths to extract file names, or just the
path portion, or just the directory name,
| | 00:17 | or just the file name without the
extension. And it turns out that the .NET
| | 00:21 | Framework provides a helper class
called the path class that makes a lot of
| | 00:25 | these operations really simple.
| | 00:27 | So if you look at the way a typical
path is built, it has a predictable
| | 00:32 | structure. And here's a sample path,
and this may look different based upon the
| | 00:37 | files you work with, but this is just a sample.
| | 00:39 | So right at the front, there's the drive
name, and it can be a letter followed by
| | 00:44 | a colon, followed by a backslash.
| | 00:46 | The drive name is the root level
of the path, and it's the disk or the
| | 00:51 | location where a file is.
| | 00:53 | That's followed by the path.
| | 00:55 | This is the directory structure that
specifies where a file is located. And this
| | 01:00 | is usually a nested set of directories,
or folders, whatever you want to call, them
| | 01:05 | that leads down to the actual file
name itself, which is right here,
| | 01:09 | somefilename, which is
usually followed by an extension.
| | 01:14 | Now not all file systems do this, but some do.
| | 01:17 | Windows, for example, does,
and this also works on the Mac.
| | 01:20 | But since we're working here on
Windows, we can pretty much be sure that most
| | 01:24 | files will have extensions.
| | 01:25 | So file extensions are usually a
period followed by some amount of characters,
| | 01:30 | usually between three and five.
| | 01:32 | So let's take a look at the path
helper class to see how we can use it to
| | 01:37 | help us work with paths.
| | 01:40 | In the Path Operations example, I've
got my snippets file open, and I've scrolled
| | 01:45 | down to the Path Operations section.
So let's go ahead and copy over the setup
| | 01:50 | code, and we'll paste it over here.
| | 01:55 | Now I'm going to be working with a
path to the testfile.txt file which we
| | 02:02 | created in an earlier example.
| | 02:03 | So if you have deleted it, you can go
just make a new file called testfile.txt
| | 02:08 | in the My Documents folder. And you can
see here that I'm using the code I used
| | 02:13 | in the earlier examples to get a path to the
MyDocument special folder here on my Windows system.
| | 02:19 | Let me make this a little
bit wider, so you can see that.
| | 02:21 | So right here, this is the MyDocuments
path, and then we're going to put the
| | 02:25 | testfile.txt on the end of it.
| | 02:27 | So this is the example
file we'll be working with.
| | 02:29 | If you don't have that already on your My
Documents folder, you should just go make one.
| | 02:33 | So what we're going to is save this,
and I'm going to go back over to the Snippets and
| | 02:37 | start copying over some of the exercises.
| | 02:40 | So I'll start with this one,
and I'll copy that and paste this over.
| | 02:47 | So the first thing we're going to do
is extract the directory name from the
| | 02:52 | path information, and to do that, we're
going to use the Path class. And again
| | 02:56 | this is a static class.
| | 02:57 | You are going to call most of these
methods using the class name followed by
| | 03:01 | the function name--in this case it's
GetDirectoryName. And you pass in thePath as the argument.
| | 03:07 | This will parse out all of the
information that's not relative to the directory
| | 03:11 | name and then just return the name of
the directory that's inside the path.
| | 03:15 | So let's save this, and let's hit F5 to run it.
| | 03:21 | And you can see here that in this
case the directory name is C:\Users\Joe
| | 03:25 | Marini\Documents, and it's parsed
out the part that is the file name.
| | 03:29 | It's giving me just the directory
name. And you can see here it is a
| | 03:32 | fully qualified path.
| | 03:34 | What I mean by fully qualified is it
starts at the drive, which is the root, and
| | 03:38 | goes all the way down to where the document is.
| | 03:42 | So it gives me the entire, full
directory structure that leads to that file.
| | 03:46 | Okay, let's go back and
do some more experiments.
| | 03:50 | The next one I'm going to do is get
the example that extracts just the file
| | 03:55 | name, so this is the opposite
of the example we just showed.
| | 03:57 | In this case, we're only going to ask
for the file name. And in this case, we're
| | 04:00 | going to use the GetFileName function
on the path class, and this will give me
| | 04:04 | the name of the file
without the directory information.
| | 04:07 | So I'll save that and run it,
and you can see here that now I've got the
| | 04:13 | directory name, and the
file name is testfile.txt.
| | 04:17 | So that function parsed out all the
information that was not relative to the
| | 04:21 | file name and just returned the
full file name with the extension.
| | 04:24 | Okay, let's go back, and let's do another one.
| | 04:30 | We'll copy and paste this one.
| | 04:31 | In this case, we're going to get
the file name without the extension.
| | 04:36 | So let's scroll down here.
| | 04:38 | You can see that the path
class provides a function called
| | 04:41 | GetFileNameWithoutExtension,
and again, it takes thePath as an argument.
| | 04:46 | So we'll save and we'll run, and in that
case, I get just the file name without
| | 04:52 | the directory and without the
three-letter extension on the end.
| | 04:55 | Okay, let's go back.
| | 04:57 | It looks like we have one more.
| | 04:59 | We're going to copy and we're
going to paste and paste this in, okay.
| | 05:07 | In this case, the path class is
going to give us a random file name.
| | 05:13 | Now you might be asking yourself, why
would I ever need to get a random file name?
| | 05:17 | What this is going to do is ask .NET to
generate some random file name for us.
| | 05:22 | It's going to consists of a certain
number of characters, followed by a period,
| | 05:25 | followed by three characters.
| | 05:28 | The reason you might want to do this is
because sometimes in your applications
| | 05:30 | you'll need to save out temporary
data and rather than going through the
| | 05:34 | exercise of trying to figure out
what file name you can come up with that
| | 05:38 | doesn't conflict with a file that's
already existing in a particular directory,
| | 05:43 | you can just call GetRandomFileName.
| | 05:46 | .NET will then figure out what file
name you can use that doesn't conflict with
| | 05:50 | a file that's already in the directory.
| | 05:52 | You can then use that file to save out
whatever temporary data you have and then
| | 05:56 | get rid of the file. And this is the
nice little utility to save you all the
| | 05:59 | trouble of having to figure out,
| | 06:00 | well, can I use this file name or can I
use that file name, without conflicting
| | 06:03 | with an existing file.
| | 06:05 | So let's just go ahead in
exercise and see what it does.
| | 06:07 | I going to run this, and you can see
that the random file name for the current
| | 06:12 | path is this sequence of characters right here.
| | 06:16 | Now if I exit the program and run it
again, you can see that it come up with
| | 06:20 | another set of characters here. And it
will keep on doing that each time I run this.
| | 06:24 | So that's a nice handy little utility
for creating random file names that you
| | 06:29 | know aren't going to conflict with
existing file names in the current directory.
| | 06:34 | So that's a quick
introduction to the path class.
| | 06:36 | I highly recommend you go look it up
on MSDN and try some more examples on
| | 06:40 | your own.
| | Collapse this transcript |
| Reading and writing files| 00:00 | The last example that we're going to
look at in this section is probably the
| | 00:03 | one you've been waiting for, and that is
actually writing and reading data to and from files.
| | 00:08 | Now, there's lots of ways to
do this in the .NET Framework.
| | 00:11 | The .NET Framework provides a
whole bunch of ways for writing data to
| | 00:14 | and reading from files.
| | 00:16 | There's probably more ways to do
this than there are ways to order sushi.
| | 00:19 | But we're only going to look at some
of the more simple ways of doing this.
| | 00:22 | I mentioned earlier that we're
not going to get deep into streams;
| | 00:24 | you can feel free to go do
that as an extra credit exercise.
| | 00:27 | What we're going to look at is the higher
level order functions for reading and writing data.
| | 00:33 | So for writing data, there are
some really simple functions.
| | 00:35 | There's File.AppendAllText, which
simply takes a bunch of text content and
| | 00:40 | appends it to the end of an existing file.
| | 00:43 | There's the WriteAllBytes and
WriteAllLines, which, as their name implies, for
| | 00:49 | WriteAllBytes you can just give it an
array of bytes; for WriteAllLines, you
| | 00:53 | give it an array of strings. They
will write out the content to the file.
| | 00:56 | And then there's File.WriteAllText.
| | 00:59 | Now, unlike AppendAllText, WriteAllText
will replace the existing contents of the file.
| | 01:05 | So if you want to just replace
the content, use WriteAllText.
| | 01:08 | If you want to add to the
existing content, use AppendAllText.
| | 01:13 | Not surprisingly, there are
some counterparts for reading data.
| | 01:16 | There is ReadAllBytes, and as you
might have guessed, this will read all the
| | 01:21 | content of a file as a bunch of binary bytes.
| | 01:25 | But for the purposes of our exercise,
we're going to be working with text, so
| | 01:29 | we'll probably use things like
ReadLines and ReadAllLines and ReadAllText.
| | 01:33 | This will actually read the
contents of a file as text content.
| | 01:38 | So let's just jump over to the code and
actually start exercising some of this,
| | 01:42 | so that you can see how it works. Okay.
| | 01:44 | In my ReadingWritingData example,
I have got my Snippets opened, and I
| | 01:48 | have scrolled down to the
Reading and Writing Files section.
| | 01:51 | So I am going to start off by copying over the
setup code, which are these lines right here.
| | 01:57 | So I will copy those and paste them in.
| | 02:00 | I'll put them in my main function. All right!
| | 02:03 | So before we go any further,
let's take a look at what's going on here.
| | 02:07 | So if you've been following the
examples up until now, you're probably familiar
| | 02:10 | with the first line here on line 14.
| | 02:12 | This is the filePath.
| | 02:14 | We're going to be using the
environment class to get the path to the
| | 02:18 | My Documents folder.
| | 02:20 | But we're going to be doing
something a little bit different this time.
| | 02:22 | If you watched the section on the
path helper class, which is previous,
| | 02:26 | you will probably notice that they
are using a path helper section here.
| | 02:31 | Instead of using the backslash character
hard coded into my examplefile.txt file
| | 02:37 | name, I am using the
Path.DirectorySeparatorChar constant, which tells me what
| | 02:44 | the separate character for
this file system happens to be.
| | 02:47 | Now, here on this version of Windows
and .NET, it will be a backslash, but it
| | 02:51 | might be different based upon what
platform you happen to be running on.
| | 02:54 | So I am going to just use this constant
right here so that I don't have to hard
| | 02:58 | code a directory separator into my
code, which is never a good idea.
| | 03:04 | So I am taking steps here to make my
code work cross-platform. All right!
| | 03:07 | So now that we've got the path built up,
we're going to see if the file exists.
| | 03:13 | And if you watched that particular
example, you will know that we use the
| | 03:16 | File.Exists function do that, here on line 18.
| | 03:20 | So we'll see if the file does not exist,
so we'll put that little not operator
| | 03:25 | right here in front of the File.Exists call.
| | 03:29 | So if the file does not exist then
we're going to create it by using the
| | 03:33 | WriteAllText function.
| | 03:35 | So we'll have a string variable here on
line 20, which will be the contents of
| | 03:40 | the file. And the content is going to
be a string called, "This is a text file,"
| | 03:43 | And once again, I am using my
environment class to figure out what the new line
| | 03:48 | character is for this particular platform.
| | 03:50 | So once again, rather than hard
coding in a /r or /n, or whatever a state
| | 03:55 | sequence happens to be the NewLine
character on this particular file system, I
| | 04:00 | will just use the NewLine
constant for this particular environment.
| | 04:04 | Then I am going to write out the console
that we're creating the file, and then
| | 04:08 | I'll use the File.WriteAllText method.
And WriteAllText takes two arguments:
| | 04:13 | the first is the path to write to, the second
is the text content that we are writing out.
| | 04:18 | So I am going to build this, and I am
going to run it. And you can see that
| | 04:25 | the Creating the file... string got
written out, because the file did not
| | 04:28 | exist in the My Documents folder.
So now we've created it, and if you want to
| | 04:33 | go ahead and check your My Documents folder to
see if it exists, you can go ahead and do that.
| | 04:37 | I am just going to keep on
moving on here. All right!
| | 04:41 | So let's go back to the Snippets.
| | 04:43 | Now, let's use the AppendAllText
method to add content to the file.
| | 04:49 | We'll copy, and we'll paste, and we'll save.
| | 04:54 | Okay, so I am going to build
this, and now I am going to run it.
| | 05:00 | Okay, now you can see that I
am adding content to the file.
| | 05:04 | Let's go back and look at the
code and see what happened here.
| | 05:07 | The file already exists, so the if
statement here on lines 18 through 23 did
| | 05:12 | not need to execute.
| | 05:13 | The file's content is getting appended,
| | 05:16 | so this line right here, Adding content
to the file... got written out, then we
| | 05:21 | use the AppendAllText to add the added
text string, which I am building up right
| | 05:28 | here into the file, and that
writes the content out to the file.
| | 05:32 | So just to make sure that things are
working okay, let's go ahead and open the
| | 05:35 | file up so we can look at the contents.
| | 05:37 | So here I am in my documents folder.
| | 05:40 | Let's open up examplefile, and you can
see, here is, "This is a text file" and this
| | 05:44 | is "Text added to the file."
| | 05:46 | Well, that's great, but I would rather
not have to open up Notepad to make sure
| | 05:49 | that the content is getting added correctly.
| | 05:51 | So let's see if we can read the contents
and display the contents into the console.
| | 05:54 | All right, so back here in the
code, let's scroll down. All right!
| | 06:02 | Now, we're going to read the contents
of the file. So I am going to copy these
| | 06:06 | lines right here and back in my code,
| | 06:11 | I am going to paste them in.
| | 06:13 | So we're going to write out to the
console that we are reading the file, and you
| | 06:17 | can see right here we're writing out
that The current contents of the file are:,
| | 06:21 | and then it will separate a
line, to separate the content.
| | 06:23 | Then we're going to use the ReadAllText
static method on the file class to get
| | 06:27 | the current content.
| | 06:28 | The current content will come back as a string.
| | 06:30 | So we've got a string variable right
here on line 35, which will hold the
| | 06:34 | results of the ReadAllText
function on the filePath.
| | 06:38 | Once we have the current content, we
will write out the current content to
| | 06:42 | the console, and then we'll put a
little line separator to increase
| | 06:46 | readability right here.
| | 06:47 | So I am going to build.
Okay, the build succeeds.
| | 06:51 | We run it, and you can see that we've
now added content to the file and The
| | 06:56 | current contents of the file are:.
| | 06:58 | And we've got a couple of lines, "This
is a text file," and then we've got "Text
| | 07:01 | added to the file" twice.
| | 07:03 | So I am going to hit Return.
| | 07:04 | I am going to run it one more time,
because each time we run it, this line right
| | 07:08 | here, the "Text added to the
file" is going to get added.
| | 07:10 | So I am going to run it again, and you
can see that now that there are three;
| | 07:14 | and then I'll run it again and
you can see that now there are four.
| | 07:18 | Okay, let's go back to the code.
| | 07:21 | One more thing I want to do here.
| | 07:22 | I want to show you how to read the
contents of the lines of the file using the
| | 07:27 | ReadAllLines function.
| | 07:29 | I want to copy this, and I am
going to paste it in over here.
| | 07:34 | This is just another way of reading the
contents of the file, so I am going to
| | 07:37 | paste that in here. And for now, I am
just going to comment out these lines,
| | 07:42 | and I am going to uncomment these lines,
so that we can actually run the code.
| | 07:52 | So whereas the ReadAllText function on
the file class will read all the content,
| | 07:58 | the ReadAllLines will read the
lines and return an array of strings.
| | 08:04 | So ReadAllText comes back with one string;
ReadAllLines comes back with an array
| | 08:09 | of strings, and that's
this right here on line 40.
| | 08:12 | So I am declaring an array of strings--
that's this contents variable right
| | 08:17 | here. Then I call the ReadAllLines
function, which will return an array, and
| | 08:21 | then here's our old friend the foreach function.
| | 08:24 | So I am going to loop over each string
that is in the contents array, and I am
| | 08:29 | going to call each one of those strings
the variable S. And inside my loop, I am
| | 08:34 | going to just write out
whatever that S string is.
| | 08:38 | So let's build, and I am going to run,
and you can see that we get the same
| | 08:44 | results, only this time, instead of
reading the content as one long string, we
| | 08:49 | read the contents as an
array of strings. All right!
| | 08:54 | That bring us to the close of this
example and this chapter, so I highly
| | 08:57 | encourage you to go explore the file
class and do some of your own experiments
| | 09:01 | working with reading and writing data to files.
| | Collapse this transcript |
|
|
10. Some Advanced C#Using variable parameter lists| 00:00 | Up until now we've been working with
some of the more basic features of C#, and in
| | 00:05 | this section we're going to start
looking at some of the more advanced features
| | 00:08 | of C# that were added in some
of the more recent versions.
| | 00:11 | Now most of the stuff that you've
seen so far you'll see in C# applications
| | 00:16 | all over the place,
| | 00:17 | but the ones that we're going to look
at now are going to enable you to write
| | 00:20 | applications that are more advanced
and have more concise code in them.
| | 00:24 | And we're going to start off by looking at
something called variable parameter lists.
| | 00:27 | Variable parameter lists are useful
because there's going to be times when you
| | 00:31 | want to create functions that take a number
of arguments that you don't know in advance.
| | 00:36 | The way that you do this is
by using the params keyword.
| | 00:40 | The params keyword allows you to define
a parameter list for function that takes
| | 00:44 | a variable number of parameters,
and it looks something like this.
| | 00:49 | Suppose I have a function that
added a bunch of numbers together.
| | 00:51 | Now, I could add a whole bunch of
numbers, but the problem is, without using
| | 00:55 | variable parameter list, I'd have
to have a fixed number of parameters.
| | 00:59 | So for example, I could supply
two integers, in this case, a and b.
| | 01:03 | But what if I wanted to add three
integers or four integers or some
| | 01:07 | unknown number of integers?
| | 01:08 | Well, I could go the route of
overloading methods, if you watched the movie on
| | 01:13 | that section, in which case, I would
just define a whole bunch of addNumbers
| | 01:18 | functions and define a version of
addNumbers that takes two arguments and then
| | 01:22 | one that takes three arguments
and then one that takes arguments.
| | 01:25 | The problem is that gets really
tedious really quickly and really bloats the
| | 01:28 | code. Or I could just simply use the
params keyword and tell my function that it
| | 01:34 | takes an array of arguments.
| | 01:36 | So, for example, rather than just adding
two numbers, I would do something like this.
| | 01:41 | And here I've used the params keyword
and following the params keyword, I say int
| | 01:47 | with square brackets.
| | 01:48 | So this tells the C# compiler, hey,
compiler, this function is going to take
| | 01:52 | an array of arguments.
| | 01:54 | And we don't know how long
that array is going to be.
| | 01:57 | So the params keyword says, just be
ready for a whole bunch of arguments.
| | 02:01 | Now once I've done that, I can rewrite
the body of this function from just adding
| | 02:05 | two numbers to adding a whole bunch
of numbers. And I'll use the foreach
| | 02:09 | construct to loop over each one of the
integers in the nums argument that you
| | 02:14 | see there in the parameter list,
and just keep a running total.
| | 02:18 | So let's jump over to the code and
actually write this example and see it work.
| | 02:22 | Here in my variable params example,
I've scrolled down to the Variable
| | 02:26 | Parameter Lists sections of my
ExampleSnippets, and the first thing we're going to do
| | 02:30 | is copy over the function.
| | 02:32 | So this is the function that's
going to add a whole bunch of numbers.
| | 02:35 | So I'll just copy this and go over to the
program code, and I'm going to paste it in.
| | 02:40 | I'll paste it down here.
| | 02:43 | So now I have my addNumbers function,
and you can see I'm using the params
| | 02:46 | keyword that takes an
integer array of arguments.
| | 02:51 | So let's exercise this.
| | 02:52 | Let's go back up to the code. And I'm
going to copy over this code here, which I'm
| | 02:56 | going to paste in the Main function.
| | 03:00 | So let's paste this in.
| | 03:03 | So let's take a look at what's happening here.
| | 03:04 | First, you'll notice that we have
two different calls to addNumbers.
| | 03:08 | There is one here on line 14.
There is one here on line 17.
| | 03:11 | The one on line 14 is passing in three
arguments, 4, 6, and 8, and then the one
| | 03:16 | here on 17 is passing in a
whole bunch of arguments.
| | 03:18 | So what's going to happen is each one
of these calls to the addNumbers function
| | 03:22 | is going to generate an array of
integers, and then inside my addNumbers, I'm
| | 03:26 | just going to loop over each one of
the integers, add it to my running total,
| | 03:30 | and then return the total back to the
caller, which will be stored in this
| | 03:34 | result variable right here.
| | 03:36 | So let's just build this and run it,
and you can see that in the first case the
| | 03:42 | result is 18, and in the
second case the result is 84.
| | 03:45 | So I've been able to now define a
function that takes a variable number of
| | 03:49 | parameters so that I can write my code
using this function and not know how many
| | 03:54 | arguments I'm going to have in advance.
| | 03:56 | Now there are a couple of things
you need to keep in mind about the
| | 03:58 | parameters function.
| | 03:59 | One of the most important ones is that
if you're going to use the params keyword,
| | 04:03 | that has to be the last
argument to the function.
| | 04:05 | What I can't do is something like this.
| | 04:09 | You'll see that when I try to do that
I get some errors, and if I mouse over it,
| | 04:13 | you'll see, "A parameter array must be the
last parameter in a formal parameter list."
| | 04:19 | The reason for this is because since
this is variable, the compiler has no way of
| | 04:23 | knowing how many arguments are in the
array, and therefore, which argument goes
| | 04:28 | in the array and which integer is the last one.
| | 04:30 | So if I wanted to do something like this,
I'd have to make sure that any other
| | 04:36 | arguments, whether they be strings or
integers or objects, all of those have to
| | 04:45 | come before the params array.
| | 04:48 | So now we see that there is no error.
Well, there is an error up here because I'm
| | 04:51 | not passing in the string integer object.
| | 04:54 | But anyway, that's how you use
variable parameters in your functions.
| | 04:59 | So using the params keyword you can
define functions that take a variable number
| | 05:03 | of parameters which greatly
simplifies code that has to work on an unknown
| | 05:08 | number of arguments.
| | Collapse this transcript |
| Using function parameter modifiers| 00:00 | Earlier on in the course I talked about
the difference between calling functions
| | 00:04 | and passing parameters by value
and passing parameters by reference.
| | 00:08 | So if you haven't watched that movie,
now is probably a good time to go watch
| | 00:11 | it, so you'll understand what's going
on here, because I am going to be talking
| | 00:13 | about function parameter modifiers
which allow you to change the way that
| | 00:18 | parameters are passed to and from functions.
| | 00:22 | So let's just take a quick recap
to see how things normally work.
| | 00:27 | Suppose I had a function that takes
an integer parameter, and it looks like
| | 00:31 | this, and inside that function, I have
a piece of code that adds the number 10
| | 00:36 | to whatever that integer parameter was passed.
| | 00:39 | Now, if I call it from another
function that looks like this, and I have an
| | 00:42 | integer named x and I initialize it
to the value of 10, and then I call my
| | 00:47 | function, the code that's inside my
function does not change the value of the x
| | 00:53 | variable in the test function down there below.
| | 00:57 | However, I can use a keyword in the
parameter list for the function called ref.
| | 01:03 | This causes a parameter to be passed
by reference, instead of having a copy of
| | 01:08 | its value passed in, which is
what the normal case is in C#.
| | 01:13 | Now what I'd do here is I would
declare my function as normal.
| | 01:16 | I'd have an integer parameter named param1,
but I would put the ref keyword in front
| | 01:21 | of the type name--in this case integer.
| | 01:24 | This causes the param1
parameter to be passed by reference.
| | 01:29 | So now here I have my test function,
and I've got my integer variable named x.
| | 01:34 | Now, when I call the function, I also
have to put the ref keyword in front of
| | 01:39 | the parameter that I'm passing to the function.
| | 01:42 | When I do this param1 is now a
reference to the x variable and not a copy of
| | 01:49 | its existing value.
| | 01:51 | This line of code here, param1 += 10,
will in fact change the value of x down in
| | 01:58 | the calling function.
| | 01:59 | X will now be equal to 20
when this function returns.
| | 02:04 | The reason why I need the ref keyword
in both places is so that it's really
| | 02:07 | clear what's going on in the code.
| | 02:10 | So you can deliberately do this when
you want to be able to change the value of
| | 02:13 | parameters that are passed to functions.
| | 02:16 | So let's take a look at one more example.
| | 02:19 | There's the out keyword.
| | 02:21 | Now, normally functions return values
through their return type, but the out
| | 02:27 | keyword allows a return value to be
passed back via a parameter, and you would
| | 02:33 | use this in cases where you wanted a function
to be able to pass back more than one result.
| | 02:39 | So let's take a look at an
admittedly contrived example.
| | 02:43 | Suppose I had a function named
SqrAndRoot, and SqrAndRoot takes a number as its
| | 02:49 | first parameter, and I want it to return
both the square of that number and the
| | 02:54 | square root of that number.
| | 02:56 | I could pass in a parameter named sq,
which would be the square, and I put the out
| | 03:01 | keyword in front of it.
| | 03:03 | I do the same thing for another
parameter named sqrt, and I also put the out
| | 03:08 | keyword in front of that
type named for that parameter.
| | 03:12 | Now, inside the body of the function, I
would simply assign values to the square
| | 03:17 | and square root results.
| | 03:19 | So for sq I'd simply multiply num by
itself, and that's the square of the number,
| | 03:24 | and then for sqrt I'm using the .NET
Framework's math library to calculate the
| | 03:29 | square root of that number.
| | 03:31 | When I call this from a function, say,
named test and I pass in the parameters,
| | 03:36 | you'll notice that I've to put the
out keyword in front of the parameters
| | 03:40 | that I'm passing in.
| | 03:41 | So when I call SqrAndRoot, I pass in
the first parameter, which is x. That's the
| | 03:45 | number I want to have
the square and square root of.
| | 03:48 | Now when this function completes,
theSquare and theRoot are going to have the
| | 03:52 | values that were calculated by
the square and root function.
| | 03:56 | You notice I don't have to actually
initialize those values, because those values
| | 04:00 | are going to be
calculated for me by the function.
| | 04:03 | So I don't have to
assign initial values to them.
| | 04:06 | Now, it's one thing to
hear me yammer on about it;
| | 04:08 | let's actually go over to the
code and actually watch it work.
| | 04:10 | Okay, so here I'm in my
FuncParamModifiers project.
| | 04:13 | I've got my Snippets open
to the code for this example.
| | 04:17 | So first, I'm going to copy this
function, which is the SquareAndRoot function,
| | 04:21 | copy that and put it over in my code.
| | 04:25 | That's the function that we're going to call.
| | 04:27 | You can see I'm using the out keyword
right here on line 10 to indicate to the
| | 04:32 | compiler that sq and sqrt
are going to be out parameters.
| | 04:37 | I'm going to copy the code, going to
call it with, and we'll put that down here
| | 04:44 | in the Main function.
| | 04:45 | Okay, I am going to put a line there.
| | 04:47 | So what we're starting
off with here is a number,
| | 04:50 | in this case 9.0, and it's a double,
and I've got variables named theSquare and
| | 04:56 | theRoot which are going to hold the results,
and now I just simply call square and root.
| | 05:00 | I pass in 9 and I've got my out keyword
in front of each one of the parameters
| | 05:04 | that are going to hold the output.
| | 05:06 | Then I've got
Console.WriteLine call that says, hey!
| | 05:09 | The square of this number is this,
and its square root is this, and I'm just
| | 05:14 | passing in those results
to the WriteLine function.
| | 05:17 | So, everything looks good.
| | 05:19 | I hit F6, and it builds just fine.
| | 05:22 | Now let's run it, and you can see that the
square of 9 is 81 and its square root is 3.
| | 05:30 | So it works just as we expected it to,
and you can use the out keyword and the
| | 05:34 | ref keywords to change the way that
parameters are passed to and from functions.
| | Collapse this transcript |
| Using optional and named function parameters| 00:00 | Okay, the next advanced C # feature we
are going to take a look at are optional
| | 00:04 | and named parameters.
| | 00:05 | Now up until now when we've been
calling functions with parameters we have been
| | 00:08 | supplying values for those parameters,
because if we don't, then the C# compiler
| | 00:13 | complains that we left a
parameter out of the function call.
| | 00:16 | Optional parameters allow you to define
default values for parameters so that if
| | 00:20 | you don't feel like passing in a value
for that parameter, you don't have to.
| | 00:24 | And the way that you do that
looks a little bit like this.
| | 00:27 | So I can define a function, and you can
see that I define the function normally
| | 00:30 | with two integer parameters. But I've
got equals and then values after each one
| | 00:35 | of those parameters.
| | 00:36 | So here for my function, I don't have
to supply values for a or for b, because
| | 00:41 | if I don't, then a will
default to 0 and b will default to 1.
| | 00:45 | So, for example, it's just as valid for
you call the function like this, where I
| | 00:49 | have got a just defaulting to 0 and b
to 1, as it is to call it like this, where
| | 00:54 | a is now 10, but b retains its default value.
| | 00:58 | The other feature is named parameters.
| | 01:00 | Now up until the version of C#, I think
it was 3.0, you had to call parameters in
| | 01:05 | the order in which they were
declared in the function declaration; named
| | 01:09 | parameters, however, changed that.
| | 01:11 | Suppose, for example, that I have
a function that looks like this.
| | 01:14 | I have got two integer arguments:
one named a and one named b.
| | 01:18 | I can actually just simply call the
function by passing in the name of the
| | 01:22 | parameter, a colon, and then
the value, and it looks like this.
| | 01:26 | So if I wanted to call this function
with parameters that are out of order, I
| | 01:29 | would simply say b:5 and a:3.
And this would call the function normally.
| | 01:35 | And you notice I don't have to do anything
special to the to the function declaration.
| | 01:38 | This just automatically works in C#.
| | 01:40 | So I can call the functions with
the parameters that are out of order.
| | 01:44 | If I wanted to call the function
otherwise, I could do it like this.
| | 01:47 | I can call the function with just the
value 3, which is now a is 3 in that case,
| | 01:52 | and I'll put the name of b:7, although
in this case I wouldn't have to do that.
| | 01:57 | Now notice that if you don't supply a
named parameter, then they have to go first.
| | 02:02 | So, for example, if I wanted to this
b:7 and then 3, that would cause an error,
| | 02:07 | because the C# compiler would say well,
wait a second. You are not supplying a
| | 02:11 | name for a, and therefore I don't know
which parameter you are talking about.
| | 02:14 | So you have to put the
non-named parameters first.
| | 02:18 | Let's go over to the code
and actually exercise this.
| | 02:21 | So here I am in my NamedOptionalParams
exercise, and in the Snippets, under the
| | 02:26 | Named and Optional Parameters section, I
am going to copy over the two functions
| | 02:30 | I am going to be using to exercise this.
| | 02:33 | So let's just copy these guys first
and paste them into the code, and I will
| | 02:38 | put them below the Main function here.
| | 02:39 | So I have got two functions.
| | 02:41 | I have got one called myoptionalParamFunc,
and you can see here that I've got a param here
| | 02:48 | that's -- param1, this is not optional
because it doesn't have a default value.
| | 02:52 | This one here is optional because it's
being supplied with a default value for
| | 02:57 | param2 and then for the third one,
which is a string, I've also got a default
| | 03:01 | value which is a string value.
| | 03:03 | And it's worth pointing out here that
you can provide default values for pretty
| | 03:07 | much just about any
parameter type you can come up with.
| | 03:10 | Inside the function all we are doing is
writing out what the function was called
| | 03:15 | with, and we will write out the
values for param0, param1, and param2.
| | 03:20 | And you will notice here that I
am using some escape sequences.
| | 03:23 | I have a \n and \t. That basically
means, do a new line and then tab in, which
| | 03:30 | will make the results a little
bit easier to read. All right!
| | 03:33 | Next, I have mynamedParamExample, in
which case I'm going to call this function
| | 03:38 | with named parameters in the
code from the Main function.
| | 03:42 | And again, you will notice, I don't
have to do anything special to the
| | 03:45 | function declaration.
| | 03:46 | This just works with normal C# functions.
| | 03:48 | So let's go back and copy over the
code that actually exercises these.
| | 03:53 | Let's start with the named parameters example.
| | 03:56 | So I will copy those lines and I
will paste them into Main. All right!
| | 03:59 | So the first thing we are going to do
is call the named parameter example, and
| | 04:05 | you can see I have got
cityName, stateName, and zipCode.
| | 04:08 | I am just going to call
them in different orders.
| | 04:10 | So the first example is going to call
it with state, zip, and then city; the
| | 04:14 | second is going to call with city then
zip and then state; and then the last one
| | 04:17 | is going to do zip, city, and then state.
| | 04:20 | So let's go ahead and exercise that.
| | 04:22 | We will build it and run it.
| | 04:26 | And you can see that in each one of
the cases the arguments were passed in
| | 04:30 | different orders, but the
output is in the right order.
| | 04:33 | So each one got its city name
correctly, the state name is correct, and the
| | 04:37 | zip code is correct.
| | 04:39 | Okay, so let's do this.
| | 04:40 | Let's go back to the Snippets, and let's
pass in the optional parameters example.
| | 04:47 | Copy this, paste it over here.
| | 04:50 | So now we are going to call the
optionalParam function, and in each one of these
| | 04:56 | cases we are going to pass
in a different set of values.
| | 04:59 | This one is going to pass in just one parameter.
| | 05:01 | This one will pass in two, and this one
will do three, and then we will get to
| | 05:05 | this one in just a moment.
| | 05:06 | So let's save and build, and now we are
going to run it, and you can see that now,
| | 05:13 | on the lower part of the
output here, I have got Called with.
| | 05:16 | In the first case, you can see that the
first parameter was 15 and then this two
| | 05:20 | second parameters were the default values.
| | 05:22 | In the second case, I passed in two
parameters, so the first two parameters
| | 05:26 | are different, but the placeholder
string is still the same. And in third case
| | 05:30 | I passed in three parameters which are
different values and all of the default ones.
| | 05:34 | So let's go back to the code and see what
happens when I uncomment this one right here.
| | 05:39 | Actually, before I do that, let me
comment these guys out to make the output a
| | 05:41 | little more readable. All right!
| | 05:42 | So I am going to save. And you'll see
that I am getting an error here, and the
| | 05:48 | reason I am getting an error is
because the best overloaded method match for
| | 05:53 | blah, blah, blah has some invalid arguments.
| | 05:55 | What that basically means is,
because I'm using optional parameters here,
| | 06:01 | you'll see that there is no version
of myoptionalParamFunc that takes an
| | 06:07 | integer and then a string.
| | 06:10 | So this is a problem here.
| | 06:11 | If I'm going to pass in parameters
that are being supplied instead of the
| | 06:15 | defaults, I have to supply values for all the
optional parameters leading up to that point.
| | 06:21 | So I can't leave out the middle
parameter here, because it thinks I am trying to
| | 06:25 | pass in a string value to this
double right here, which is not correct.
| | 06:29 | So if you are going to use optional
parameters and you want to supply values for
| | 06:33 | parameters in different
orders, you will probably have to use the
| | 06:36 | named parameters and optional
parameters in the same function call, which is
| | 06:40 | what we are going to do right now.
| | 06:41 | So let me comment that back out to
get rid of the error. Now do both.
| | 06:49 | So to fix the error that I had above,
what I am going to do pass in the value
| | 06:55 | for the first parameter, because it's mandatory.
| | 06:58 | There is no default value here, so I
have got to supply a value to that, but
| | 07:01 | I want to skip over the middle parameter
and just provide a string for the last one.
| | 07:05 | So to do that, I'm combining the
named parameter feature with the optional
| | 07:11 | parameter feature. And now the compiler
is like, oh, I see, you're trying to
| | 07:14 | supply a string for param3, which
is over here, and not for param2.
| | 07:21 | Okay, well, that's fine with me.
| | 07:23 | So let's go ahead and build, and let's
run it, and you can see now that all the
| | 07:28 | cases work. And this is the
most recent case we just added.
| | 07:31 | So we have got the mandatory value here,
| | 07:34 | the default value is now being passed in
for param2, and in the last case we have
| | 07:38 | a different string being passed in for param3.
| | 07:41 | So optional and named parameters really
allow you some great flexibility in how
| | 07:45 | you define your functions.
| | 07:46 | They allow you to define default
values for parameters that you don't want to
| | 07:51 | make mandatory for the caller,
and named parameters allow you to call functions
| | 07:55 | with parameters in different orders.
| | Collapse this transcript |
| Using the C# preprocessor| 00:00 | During your C# coding travels,
you're probably going to come across C#
| | 00:04 | preprocessor directives, and that's we
are going to cover in this particular movie.
| | 00:08 | The preprocessor is what its name implies.
| | 00:11 | It does some pre-processing of the
files before the compiler actually goes and
| | 00:17 | looks at all the code and
compiles the application.
| | 00:20 | The preprocessor directives simply
give instructions to the compiler
| | 00:24 | which help the compiler do its job
before the compilation process actually runs.
| | 00:29 | Preprocessor directives are preceded by
a hash character, or a pound character, or
| | 00:35 | whatever you want to call it.
| | 00:36 | So we'll take a look at some of those here.
| | 00:38 | The first two are define and undef,
and you can see that they have got that
| | 00:42 | little--I guess you can call it sharp
character, if you want to, whatever is it,
| | 00:45 | it has a word preceded by that little character.
| | 00:49 | In this case, define and undef allow
you to define or undefine a symbol.
| | 00:55 | Now, why would you want to do that?
| | 00:56 | Well, we will take a look at an
example that explains why you would want to
| | 00:59 | do that in just a moment, but there are a
few other directives we want to look at first.
| | 01:03 | Using preprocessor directives,
you can also do things like logic.
| | 01:06 | You can use #if, #else, #elif, or #andif,
and these allow you to use logic to see
| | 01:13 | if a certain symbol is defined.
| | 01:15 | Now if the light bulb hasn't gone off yet,
don't worry; it will in just a moment,
| | 01:18 | but there are two more
directives we want to take look at.
| | 01:20 | They are region and nregion, and these
are used for documenting your code, so that
| | 01:27 | the C# Express development
environment allows you to do things like label
| | 01:31 | regions and collapse regions and so on.
| | 01:34 | But rather than just talk about them,
let's actually see them in action, because
| | 01:37 | slides just don't do it justice.
| | 01:39 | Let's jump over to the code.
| | 01:40 | I have got my preprocessor example
open here, and here is my program file.
| | 01:46 | The first thing I am going to do is this:
| | 01:48 | I am going to do a couple of defines.
| | 01:51 | Now, if you're going to define symbols,
you need to do it before any other line
| | 01:56 | of code in the file.
| | 01:57 | So I need to put these defines up here
above the using statements; otherwise, this
| | 02:01 | will cause problems.
| | 02:02 | So if I try to take these out and
put them down here and save, you'll see
| | 02:07 | that these little red squiggles show up,
and that's because the compiler is complaining.
| | 02:11 | It says hey, you cannot define or
undefine preprocessor symbols after the
| | 02:15 | first token in the file. And that's just a
fancy way of saying, these got to come first.
| | 02:20 | So let's go ahead and cut
those and put them back up there.
| | 02:25 | So now I have defined some symbols,
but what exactly does that mean. Why am I
| | 02:28 | defining symbols in the first place?
| | 02:30 | Well, the reason for doing this will
become clearer when we paste in the rest of
| | 02:34 | the example. And I am going to go ahead
and paste these guys in down here, copy,
| | 02:39 | and I'll put these in the
Main part of my program.
| | 02:43 | So what you'll do here is you will
notice that when I've got these #if and #else
| | 02:48 | and #endif, they are checking to see
if a particular symbol has been defined.
| | 02:53 | So let's imagine that you're building
a version of your application where you
| | 02:56 | only want to include some code if it,
say, in a debug configuration, or if
| | 03:03 | it's in a demo mode.
| | 03:04 | Suppose I wanted to have this code
right here only included in my application
| | 03:10 | if I'm shipping a demo version of my
application, versus a fully released, fully
| | 03:15 | functional version.
| | 03:16 | Well, in that case I can simply change
this from the DEBUGCODE to DEMOMODE or
| | 03:21 | whatever it is that I want.
| | 03:22 | You can see I have also
defined a JOE symbol here.
| | 03:26 | I can make up whatever symbol I name I want.
| | 03:27 | Now, what's going to happen is the
compiler is going to come across this logic
| | 03:30 | and say #if DEBUGCODE. Okay, well, if
there's a symbol name DEBUGCODE then the
| | 03:36 | code that's in between this #if and
#else is going to be included in the
| | 03:42 | compilation process and code that does not
meet that logic test is not going to be included.
| | 03:47 | You can see here on line 18
that this code is in gray.
| | 03:51 | That's because the
compiler is going to ignore it.
| | 03:53 | I can just write things that's not
even code in here. Watch!
| | 03:56 | No red squiggles, right? Why?
| | 03:58 | Because the compiler is completely
ignoring this code; it's not meeting the
| | 04:02 | logical test to see if the
DEBUGCODE symbol is present.
| | 04:05 | Let me go ahead and delete that.
| | 04:08 | So now if we build and run--let's just
do that really quickly, build and run;
| | 04:12 | we will hit F5--you'll see that the
lines of code that met the logical tests of
| | 04:18 | those preprocessors was included in
the application and they are executing.
| | 04:22 | So let me hit Return and get out of here.
| | 04:24 | Now let's go back up to the top.
| | 04:26 | What I am going to do is I am going to
take out this #define for JOE, and we'll save.
| | 04:31 | Now watch, notice how the line of code
that's inside this #if, #endif section
| | 04:37 | for the JOE symbol went and turned gray.
| | 04:40 | That's because I've gotten rid of the
JOE symbol and this line of code is no
| | 04:44 | longer relevant, because this logical
test on line 20 no longer evaluates to true.
| | 04:49 | Similarly, I can get rid of the
#define DEBUGCODE, and you'll notice that the
| | 04:54 | line of code that used to be included
in the compilation process when DEBUGCODE
| | 04:59 | was defined is now gray and the
else condition is now being included.
| | 05:03 | So this bright line right here, it says:
| | 05:06 | "This only gets written out in non-
debug code" is going to execute.
| | 05:09 | So if I run this now, you will see
that that line of code is getting executed
| | 05:13 | where the other lines of
code are not getting executed.
| | 05:15 | In fact, they are not
even included in the program.
| | 05:17 | If you were to disassemble this code
using a disassembler, you'd notice that
| | 05:21 | those lines of code aren't even
present in the final application. Okay.
| | 05:25 | So let's take a look at one more preprocessor
directive, and that is the region directive.
| | 05:30 | What I am going to do is
copy this right here, #region.
| | 05:33 | I am going to put that in front of the
Main, and then I am going to copy the
| | 05:40 | endregion. And I am going to put
that below the Main function right here.
| | 05:48 | Now when I save, what that does is it tells
the C# compiler that this is a region of code.
| | 05:53 | Now, this doesn't affect compilation.
| | 05:55 | It's really just for documentation,
because watch what I can do now.
| | 05:58 | Over here in the C# Express IDE, I can
click on this little collapse button and
| | 06:04 | you can see that it collapses down,
and the text that I've included after the
| | 06:07 | region declaration here on line 10 is
what gets included in that little label.
| | 06:12 | So I can collapse that down and you
can see now that all that code is hidden.
| | 06:16 | So if I wanted to just collapse my
code down to make it easier to read, I can
| | 06:20 | separate my code into different regions and
then expand and then collapse them as I see fit.
| | 06:25 | Now if you're coming from other
languages, such as C or C++ or Objective-C,
| | 06:31 | you'll probably see sometimes these
preprocessor directives used to define
| | 06:36 | constants, and you'll see the #define
directive used to define numbers and so on.
| | 06:43 | That's not the way things are done in C#.
| | 06:46 | In C# we have the const keyword,
which we discussed earlier in the course
| | 06:50 | for defining constants.
| | 06:52 | So if you're coming from a language
like C where you're used to using the
| | 06:55 | #define preprocessor directive to define
constant values, you are not going to do that here.
| | 07:00 | You can use the const keyword instead.
| | 07:02 | Here, we are going to use the #define
and #undef and so on, just to affect the
| | 07:07 | way that compilation happens.
| | Collapse this transcript |
| Working with delegates| 00:00 | Next couple of subjects that we are
going to take a look at are fairly advanced,
| | 00:04 | and they are delegates and events.
| | 00:07 | I am going to start off by
taking a look at C# delegates.
| | 00:10 | C# delegates are sort of like callbacks
that you may have seen in other languages.
| | 00:14 | If you're familiar with programming
languages such as JavaScript or Java or C or
| | 00:20 | C++, then you're probably familiar
with the notion of a callback function.
| | 00:25 | A callback function is assigned at
runtime and you can change callback functions
| | 00:29 | while the program is running. And the
callback function is simply a way for you
| | 00:33 | to provide a piece of functionality
that can be switched in and out as it is
| | 00:37 | needed. And delegates
provide that functionality in C#.
| | 00:40 | Essentially, a C# delegate decouples
the caller of a function from the call
| | 00:46 | function, which is essentially
the same thing that callbacks do.
| | 00:49 | So to declare a delegate use the
delegate keyword, and you're essentially
| | 00:53 | defining a type of function
that is going to be called.
| | 00:57 | So I use the delegate function. Then
I provide the type that the delegate
| | 01:02 | is going to return.
| | 01:03 | So in this case I'm declaring a delegate
that returns an integer. Then I need to
| | 01:08 | provide a name for the delegate,
and I can make it up as much as I want to.
| | 01:12 | I can use whatever a legal function name would be.
| | 01:15 | In this case I am just using the
generic term delegateName, but you can use
| | 01:18 | whatever name you want. And then you
have to provide any parameters that the
| | 01:22 | delegate is going to handle.
| | 01:23 | In this case I'm declaring a delegate that
returns an integer and takes two parameters:
| | 01:27 | there is an integer and a string.
| | 01:30 | Then when I want to use the delegate, I
use it like any other kind of type name.
| | 01:34 | So in this case I'm declaring a
variable named func, which is of type
| | 01:40 | delegateName, and I'm
assigning it to be someFunction.
| | 01:43 | So as long as I declare someFunction to
be the same format as the delegate that
| | 01:48 | I have declared above, I can switch
that function in and out as much as I like.
| | 01:52 | Then I just call the function
like I would any other function.
| | 01:55 | In this case I've got an integer
result which is being assigned
| | 01:59 | to the result that comes back from the
func variable, which is now pointing at
| | 02:03 | the someFunction function, and it takes the
integer argument 3 and the string argument "hello."
| | 02:09 | Then all we have to do is actually
write the someFunction callback. And you can
| | 02:14 | see here that I've got a function
named someFunction, which returns an integer
| | 02:18 | and takes two parameters--an integer
and a string--and it has the same format as
| | 02:23 | the delegate that I declared
at the top of the slide there.
| | 02:27 | So let's jump over to the C# code and
actually implement this and see how it works.
| | 02:32 | Okay, so I am here in my delegate
example, and I've got the UsingDelegates
| | 02:37 | project open, and I have also got the
ExampleSnippets file open, and I've scrolled
| | 02:42 | down to the section on using delegates.
| | 02:45 | So the first thing I am going to do
is copy my delegate declaration.
| | 02:49 | That's this line right here, so I
will copy that and I will paste it into
| | 02:52 | the Main program here.
| | 02:55 | Now I am going to paste this inside the
namespace but outside of my program class.
| | 03:00 | So I will just put it up here. And this
basically says to the C# compiler, hey
| | 03:04 | compiler, there's going to be this
thing called a function that has the format
| | 03:08 | of returning an integer and taking an
integer argument, so be on the lookout for it.
| | 03:14 | So I am going to save that,
go back to the snippets.
| | 03:17 | Now I am going to scroll down
here and copy these two functions,
| | 03:21 | the functions Square and Cube.
| | 03:24 | So let's copy these guys, and we'll put them
in the code outside of the Main function.
| | 03:31 | Now notice how each one of these
functions returns an integer and takes an
| | 03:36 | integer argument, just like
the delegate is declared up here.
| | 03:41 | So this delegate returns an integer and
takes an integer argument. All right!
| | 03:45 | Now we can write the code
that actually uses the delegate.
| | 03:48 | Here is what we are going to do.
To do that, we are going to go back over to
| | 03:52 | Snippets and we are going to
copy this piece of code right here.
| | 03:57 | Let's put this in our Main function.
| | 04:00 | Let me explain what's going on here.
| | 04:02 | Now that I've defined my delegate as a
NumberFunction--that's this guy right
| | 04:07 | here--I can now declare that as a variable.
| | 04:10 | So on line 15 I am creating a variable
named f which is of type NumberFunction,
| | 04:16 | and remember, that's a delegate.
| | 04:17 | So I can assign to f the name of a function
that matches the same description as the delegate.
| | 04:24 | In this case, it's the Square function.
| | 04:27 | So down here is the Square function.
| | 04:29 | It takes an integer argument, and it just
simply returns the square of that number.
| | 04:32 | It takes that number and
multiplies it by itself.
| | 04:36 | So, on the next line, on line 16, I am
doing a Console.WriteLine that says. the
| | 04:41 | result of the delegate is. and then the
result number is going to go in here, and
| | 04:45 | then I simply call the
function f with the number 5.
| | 04:48 | So f is now pointing at the Square
function, because I assigned it to that up here on line 15.
| | 04:52 | So, I am going to call the function f
with 5, and that's going to square the number.
| | 04:58 | That's going to write out the number 25.
| | 05:01 | So let's go ahead and run that.
But before we run, that let's comment out these
| | 05:04 | two lines, so we can isolate the
results for the moment. All right!
| | 05:07 | So we will save and we will run,
and you can see that the string that's being
| | 05:12 | written out is the "result of the
delegate is 25," just as we expected.
| | 05:16 | Okay, so far so good.
| | 05:17 | Now what we're going to do is
uncomment these lines. And notice I'm changing
| | 05:21 | the delegate on the fly.
| | 05:23 | So now, instead of the f variable
pointing at the Square function, it's going to
| | 05:28 | point at the Cube function.
| | 05:30 | So, while the program is running,
I'm changing what the function that's going to
| | 05:34 | be called is, by changing the value
of the f variable from Square to Cube.
| | 05:39 | So now this f variable right here on
line 19 is going to be pointing at this
| | 05:44 | function down here to Cube.
| | 05:45 | And Cube takes the number and
multiplies it by itself three times, which is how
| | 05:50 | you arrive at the cube of a number.
| | 05:53 | So on line 20, I am going to write out the
result of the delegate is, and then the result.
| | 05:58 | I am going to call the function the same way.
| | 06:00 | I am going to call the function f
with the value of 5, but in this case the
| | 06:04 | result is going to be very different.
| | 06:06 | So we should see two things written out.
| | 06:08 | We should see this line written out
here, when f is pointing at the Square
| | 06:12 | function, and then we should see a
different value written out here, when f is
| | 06:17 | pointing at the Cube function.
| | 06:19 | So let's build, and we can
see the Build succeeded.
| | 06:21 | Okay, let's run it.
| | 06:24 | And you can see that the result of the
delegate is 25, and then the result of
| | 06:29 | the delegate is 125, which is what we
would expect, because we changed the
| | 06:34 | delegate to point from Square
function to the Cube function.
| | 06:38 | Delegates are a really powerful and
flexible programming construct in C#.
| | 06:43 | They do the same thing as callback
functions, but they do it in a more modular way.
| | 06:48 | If your code calls for such
flexibility, such that you need to be able
| | 06:51 | to provide callback functions, the
way that you accomplish that in C# is by
| | 06:55 | using delegates.
| | Collapse this transcript |
| Handling events| 00:00 | In this example we're going to see how
to use C# events, and specifically we're
| | 00:04 | going to create our own
events and our own event handler.
| | 00:08 | Now the work in this particular
movie is based on the delegates movie.
| | 00:12 | So if you haven't watched that one, you
go back and watch it now because events
| | 00:16 | need delegates to work, and it's
important that you understand delegates before
| | 00:20 | you attempt this movie.
| | 00:21 | So there are four steps involved in
declaring and triggering C# events.
| | 00:27 | The first is that we have to create a
delegate which is the event handler.
| | 00:30 | And just like we did in the previous
section, we do that by using the delegate
| | 00:34 | keyword and then we declare the
delegate named. In this case have got an
| | 00:39 | EventHandler which returns a void value.
| | 00:42 | So there's no return value from this function.
| | 00:44 | And then I declare the parameter list.
| | 00:47 | In this case, there is an integer
parameter and a string parameter.
| | 00:51 | Now inside the class that's going to
implement this event, I need to use the event keyword.
| | 00:55 | So what I do is I define a my class,
and I do that normally with my class
| | 01:00 | definition. And then somewhere in
my class I do something like this.
| | 01:03 | I say public and then the word event in
front of the EventHandler delegate name,
| | 01:10 | and then I give it a name which is
going to be used by the consumer of this
| | 01:14 | class to hook onto my event.
| | 01:17 | So somewhere else in the code someone
who is using this class is going to write
| | 01:21 | something like this.
| | 01:22 | They'll write myClass and then
some variable name, in this case object
| | 01:25 | equals new my class.
| | 01:27 | So now they've created
an instance of this class.
| | 01:30 | Now what they want to do is listen
for, or sometimes the word subscribe is
| | 01:34 | used, to this event.
| | 01:36 | To do that, they'll use the myEvent
property which I've declared up there in myClass.
| | 01:42 | They'll use the += operator to
specify a handler function that will be used
| | 01:49 | to handle that event.
| | 01:51 | This is called subscribing to an event,
and it adds the handler function to the
| | 01:55 | list of functions that the
myEvent is going to broadcast to.
| | 01:58 | Then what all I have to do
is declare that function.
| | 02:01 | Here I've got a handler function,
and notice that it matches the same format as
| | 02:05 | the delegate that I declared
in the first line up there.
| | 02:08 | It say void function, and it takes two
parameters, an integer and a string, and
| | 02:13 | then it implements whatever code there is.
| | 02:15 | Now this is the function that's going
to be called whenever that event happens.
| | 02:20 | And you can see that there's the +=
operator. That subscribes to the event.
| | 02:24 | If you wanted to have your code to stop
listening to an event, you would simply
| | 02:28 | use the -= operator and the same name of
the function that you used to subscribe with.
| | 02:34 | So let's take a look at
this in action in real code.
| | 02:37 | All right, so I've got my
UsingEvents example open, and here is the
| | 02:42 | program code, and over in my snippets I've
scrolled down to the using the events section.
| | 02:46 | So let's just take this one step at a time.
| | 02:48 | I'm going to first copy over the
delegate declaration for myEventHandler.
| | 02:52 | So I am going to copy that and paste
it inside my namespace here, outside my
| | 02:57 | program class. And this basically tells
the C# compiler, hey there's going to be
| | 03:02 | this thing called a delegate which is
an event handler and it takes a string
| | 03:05 | argument, and I'll supply that later.
Don't you worry about it, but it's going
| | 03:08 | to be coming along.
| | 03:09 | Okay, now let's go ahead and declare a
class, and this as an example class that's
| | 03:15 | just going to raise an event that other
people can listen to. And I'll put that
| | 03:20 | class declaration up here above my program.
| | 03:22 | So let's take a look at the class
declaration, and then we'll go further.
| | 03:26 | Here in my class I've got a member
variable for this class on line 13, and
| | 03:30 | it's called theValue.
| | 03:31 | I've also got an event handler
for valueChanged here on line 14.
| | 03:37 | So whenever this string value here
called the value changes I'm going to
| | 03:42 | raise an event so that people who are
using this class can listen for it and
| | 03:46 | say, oh, the value changed.
| | 03:48 | Then I've got a property right here
starting on line 16. And if you are not
| | 03:53 | familiar with properties, you can go back and
watch the section of this course on properties.
| | 03:58 | But I am exposing a public string
property named val, and you'll notice that I am
| | 04:02 | only supplying a setter
which starts here on line 18.
| | 04:06 | So the setter does two things.
| | 04:07 | First, it sets the value of theValue
member variable to whatever the value
| | 04:13 | supplied to the property was.
| | 04:15 | And then it calls the value
change event here on line 21.
| | 04:20 | So anyone who is subscribed to
listening to this event is going to get notified
| | 04:25 | that the value has changed.
| | 04:27 | And it passes in the value of this
private--the value member right here as
| | 04:33 | the first argument.
| | 04:35 | All right, so all that's left to do now
is go back over to the Snippets and copy
| | 04:41 | over the code here that listens for the
event, and I will put that in my Main.
| | 04:50 | So let's go through this line by line.
| | 04:53 | Here on line 30 I am creating a new
instance of my event example class, and
| | 04:59 | that's this class right here--
the one that implements the event.
| | 05:02 | And I have got a variable called myEvt.
| | 05:06 | Then on line 32 I say
myEvt.valueChanged, which is the name of the event.
| | 05:11 | All right scroll back up.
| | 05:13 | You can see there on line 14,
that's the value changed event, +=new
| | 05:19 | myEventHandler, which is the name of the
delegate. And then I need to supply the
| | 05:25 | name of the function that's going to
handle that event. And the reason there is
| | 05:28 | a red squiggle there right now is because I
haven't declared the my Evt_value changed function.
| | 05:34 | So let's go do that right now. Back
over in the snippets I'm going to copy this
| | 05:39 | function right here.
| | 05:40 | This is my Evt value changed, and I am
going to copy that and paste it, and I am
| | 05:46 | going to paste it below the Main function.
| | 05:49 | So now you can see the little red
squiggle error has gone away, because now I
| | 05:52 | have a function which is
going to handle the event.
| | 05:55 | And let's just take a quick
look at the event handler.
| | 05:57 | So here on line 46, you can see that in
the function all we do is just write out
| | 06:02 | the value of that
argument that was passed to us.
| | 06:06 | And if we scroll back up to the class,
remember that when we call this event
| | 06:10 | we are going to pass in the string that
is represented by the private, the value
| | 06:15 | member of my class here.
| | 06:17 | So now we're pretty much about
done; all we need to do is take a look at
| | 06:21 | what lines 34 through 41 are doing.
| | 06:23 | What I've got here is a string variable,
and then I have a dowhile loop. And what's
| | 06:29 | going to happen is I'm going to read a
line of text from the console, and if that
| | 06:34 | string is not equal to the value of exit,
I'm going to set the public property of
| | 06:40 | the myEvt object to that string.
| | 06:43 | Let's scroll back up.
| | 06:45 | That's going to cause the
setter of this property to trigger.
| | 06:48 | It's going to set the value of the
theValue member variable to that string, and
| | 06:54 | then it's going to trigger the event.
| | 06:56 | And so this loop is going to just keep right
on executing until I type in the word exit.
| | 07:02 | And when the word exit gets entered,
the program will terminate, because there's
| | 07:05 | no more code after this in the Main function.
| | 07:07 | All right, so let's actually run this.
| | 07:10 | Okay, so now the program is
waiting for me to put in the string, and I am
| | 07:14 | going to put in the word Joe. And you
can see that when I set the value of that
| | 07:19 | string, the event handler gets triggered.
| | 07:22 | My event handler gets called.
| | 07:24 | The string gets passed in as the argument
and we are just writing out that string.
| | 07:28 | I can type in anotherstring.
| | 07:32 | And once again, the event handler gets
called. I can yet another string, and I can
| | 07:37 | go on and on like this, but now I am
just going to change the value to exit, and
| | 07:43 | then the program terminates.
| | 07:45 | So that's how you declare an event
handler and an event in C# using
| | 07:50 | delegates and the event keyword.
| | Collapse this transcript |
|
|
11. Garbage CollectionHow garbage collection works| 00:00 | Earlier in the course, you may have
heard me refer to C# and .NET as a
| | 00:04 | managed-code environment.
| | 00:05 | What that basically means is that the
.NET Framework provides automatic
| | 00:09 | memory management for you.
| | 00:10 | You as the programmer are not
responsible for freeing up the memory that your
| | 00:15 | program's objects use during the
course of the running of your program.
| | 00:20 | Now, this is not like other languages.
| | 00:22 | In languages like C and C++ and
Objective-C, you as the programmer, when you
| | 00:28 | create objects that take up memory,
you are responsible for making sure that
| | 00:31 | that memory gets returned
to the system at some point.
| | 00:35 | But languages like .NET and other
language like JavaScript in Java and so on,
| | 00:39 | those are managed-code environments.
| | 00:41 | There are ways that the system figures
out that memory is no longer being used
| | 00:45 | by your program and reclaims it automatically.
| | 00:48 | Now, to take a simple example,
when you do something like this in your C#
| | 00:52 | program, you have some object type
definition, maybe you've made a new class,
| | 00:56 | and you use the new operator to
create a new instance of that object,
| | 01:00 | that allocates memory somewhere in the
system. That tells .NET, hey, you've got
| | 01:05 | to go find some memory to hold my object.
| | 01:08 | And the Framework will take care of figuring
out when this object is no longer being used.
| | 01:12 | You don't have to do anything special.
.NET will just figure out that you're
| | 01:16 | done using this object, and it will put
the memory back in the system for you.
| | 01:20 | So let's take a look at
conceptually how this works.
| | 01:23 | There is a big pool of memory available
to the system, and we can think of it as
| | 01:27 | this big purple box you see right here.
| | 01:30 | Now, your program is going to use
this memory during the course of its
| | 01:34 | operation. And as your program runs,
it's going to allocate blocks of memory and
| | 01:39 | when it does that those blocks of memory
are going to be taken out of the system
| | 01:43 | memory pool and assigned to your
program. And then in your program will do
| | 01:46 | whatever it does with that
memory and all these objects.
| | 01:49 | At some point there is a special
class in the .NET Framework called the
| | 01:53 | Garbage Collector, and garbage
collection is the process by which .NET figures
| | 01:58 | out that memory is no longer being used by
your program and can take it back into the system.
| | 02:04 | So the Garbage Collector has a way of
keeping track of the objects that you have
| | 02:07 | allocated, and when it figures out that
these objects are no longer being used,
| | 02:11 | it simply puts them back
in the system memory pool.
| | 02:14 | This process is completely
invisible to your program.
| | 02:17 | You don't have to worry about doing this at all.
| | 02:18 | It all just happens for you.
| | 02:20 | So let's take a look at
how garbage collection works.
| | 02:23 | Suppose we have a function, looks like this.
| | 02:26 | It's called myFunction. And inside
myFunction I've got this new MyObject.
| | 02:32 | Well, out in the system memory pool
when I do that, a block of memory is going
| | 02:35 | to be allocated that holds MyObject.
| | 02:37 | That creates what's called a reference.
| | 02:40 | That myObj variable that you created
inside your function is now going to hold a
| | 02:44 | reference to that memory location.
| | 02:47 | Now, you can go and do a bunch of things:
| | 02:49 | you can call a method, you can set a
property, you can call SomeOtherMethod.
| | 02:54 | But when that function ends, that
myObj variable is going to go out of scope.
| | 02:59 | And at that point there are no more
references to MyObject. Because that
| | 03:03 | variable is gone now, that little
reference line disappears. And the Garbage
| | 03:07 | Collector comes along and says, hey,
no one is using that thing anymore.
| | 03:10 | I can just return that
object back to the memory pool.
| | 03:14 | So what are some important things
to know about garbage collection?
| | 03:17 | First, your program does not need
to initiate this process; the Garbage
| | 03:21 | Collector figures out when it
needs to run and reclaim memory.
| | 03:25 | Now, there is a way for your program
to initiate garbage collection, and we'll
| | 03:28 | actually take a look at that
in an example in just a bit.
| | 03:31 | The Garbage Collector balances between
performance and app memory usage, and the
| | 03:38 | objects are not
necessarily reclaimed right away.
| | 03:41 | So these two things mean that you, A,
don't know when Garbage Collection
| | 03:47 | is going to happen.
| | 03:48 | The Garbage Collector tries to figure
out how your program is doing its work and
| | 03:52 | how much memory is being used, and it
tries to strike a balance between making
| | 03:57 | sure that your application doesn't take
a performance hit while figuring out how
| | 04:02 | much memory is being used and trying to
say, okay, well, memory use is getting
| | 04:05 | kind high, maybe I should go
take some of that memory back.
| | 04:08 | The other thing you need to realize
that when you're finished with an object,
| | 04:11 | it might stick around for a while until the
Garbage Collector figures out that it needs to run.
| | 04:15 | Now, objects can detect that they are
about to be released from memory, so
| | 04:20 | when you create an object in a class, you can
actually write a method called the finalizer.
| | 04:25 | Now, this is rather advanced.
| | 04:27 | I'm not going to cover it in this course.
But you can just be aware that there
| | 04:31 | are ways for your objects to figure out
that they're about to be released back
| | 04:35 | into the system memory pool.
| | Collapse this transcript |
| The Garbage Collector object| 00:00 | Let's take a look at a real example to
see how garbage collection actually works.
| | 00:04 | So I've got my Garbagecollection
project open up here, and in my Snippets file I
| | 00:09 | have scrolled down to the
Garbage Collection section.
| | 00:11 | So let's go ahead and take a look at
some of the garbage-collection routines
| | 00:16 | that are available to us.
| | 00:18 | So first I'm going to copy these three
lines and paste them into my application.
| | 00:24 | Now there is a global object in .NET called GC.
| | 00:29 | You can see I'm using
that right here on line 12.
| | 00:32 | The GC object is the Garbage Collector,
and I'm going to call a function on the
| | 00:38 | GC object which is a static function
here called GetTotalMemory. And it takes a
| | 00:43 | parameter--I'm not going too deeply into
this. Don't worry about what this does.
| | 00:46 | Basically I'm saying to Garbage
Collector, hey, tell me how much total memory is
| | 00:50 | currently allocated to my application.
| | 00:52 | So this is a pretty simple place to start.
| | 00:54 | Let's just build this and
run it and see what happens.
| | 00:56 | So I'm going to run it, and the console
is going to write out how much allocated
| | 01:00 | memory there is to my app. And you can
see that when I run this the amount of
| | 01:05 | memory that's allocated to my
application right now is 186,836 bytes.
| | 01:10 | Now don't worry if this number looks
different for you and your example. This is
| | 01:14 | going to different for everyone's system.
| | 01:16 | This is basically how much memory
is currently allocated to my app.
| | 01:20 | So let me hit Return, and we'll exit the app.
| | 01:23 | Okay, let's go back to the snippets
and paste in some more information.
| | 01:26 | So the next few lines I am going to
copy right here, and I'm going to paste
| | 01:29 | those below these lines.
| | 01:32 | So starting on line 16, I'm going to allocate
100,000 bytes in an array that holds bytes.
| | 01:40 | So this is 100K of memory that I'm
going to allocate, and then I'm going to
| | 01:44 | basically do the same thing here on
lines 18 through 20 that I do at the
| | 01:49 | beginning of program. And we'll see if
this makes a difference in how much memory
| | 01:52 | that Garbage Collector thinks
is allocated to my programs.
| | 01:55 | So let's run, and you'll see that
we start off with 186,000 bytes.
| | 01:59 | Now let me hit Return, and this is
going to cause the allocation to happen.
| | 02:03 | And now you can see that the amount of
memory allocated to my app is 295,060 bytes.
| | 02:09 | Now notice it's not exactly 100,000
bytes more than the original size. Again,
| | 02:15 | don't worry too much about that,
and don't worry too much if this number looks
| | 02:19 | different for you on your system.
| | 02:21 | The .NET Framework keeps track of a
whole bunch of overhead internally, so when
| | 02:26 | I allocated those 100,000 bytes, a lot
of other things happened under the hood.
| | 02:31 | So it looks like more memory got
allocated then I asked for, but that's just the
| | 02:35 | .NET Framework doing its work.
| | 02:36 | So let's go back to the application.
| | 02:40 | Now what we're going to do is actually
trigger the garbage-collection process,
| | 02:44 | so I am going to copy these lines here,
and I'm going to paste them in here.
| | 02:49 | And you'll notice that on line 22 I'm
calling the Garbage Collector's collect method.
| | 02:54 | This will actually trigger
the garbage-collection process.
| | 02:58 | So we're going to start off by seeing
how much memory my application gets when
| | 03:02 | it starts. Then we're going to allocate
a whole bunch of memory and see how much
| | 03:06 | that changes things.
| | 03:07 | Then we're going to call the Garbage
Collector's collect function which will
| | 03:11 | cause the Garbage Collector to go out
and look at memory and say, hey, how much
| | 03:14 | memory isn't being used and how much
can I reclaim? And that's going to be this
| | 03:19 | line right out here. We're going to
write out what the results of that are, so
| | 03:22 | let's save this and run it.
| | 03:25 | Okay so we start with 186k. It goes up
to 295k. Now let's watch what happens
| | 03:32 | when the Garbage Collector runs
and we call that collect function.
| | 03:34 | Okay, it looks like the allocated
memory dropped back down to about 210,000,
| | 03:40 | almost 211,000 bytes.
| | 03:42 | Again, I didn't get all hundred thousand
bytes back, and that's because, as I said,
| | 03:48 | earlier the .NET Framework has some
overhead that it's working on. So it did
| | 03:52 | figure out, however, that those bytes
actually aren't being used by anybody.
| | 03:56 | So I was able to reclaim those bytes by
running the garbage-collection process.
| | 04:01 | Now again, I want to emphasize that this
is just an academic exercise here and
| | 04:05 | shows you how the Garbage Collector works.
| | 04:07 | There are going to be very few
instances in your C# career when you're going to
| | 04:11 | have to actually care about
running the Garbage Collector, if ever.
| | 04:15 | I've been working with C# for a long time.
| | 04:17 | I've never actually had to do this.
But it interesting to see how the Garbage
| | 04:20 | Collector works and what you can do with
the Garbage Collector to figure out how
| | 04:24 | much memory your application is consuming.
| | Collapse this transcript |
|
|
12. DebuggingCommon compilation issues| 00:00 | In the long, and no doubt illustrious, C#
coding career that lies before you, you
| | 00:06 | are going to have to deal with compiler
issues and bugs, and that's what we're
| | 00:10 | going to talk about in this section,
debugging, and we're going to start off with
| | 00:14 | dealing with common compilation issues.
| | 00:17 | Now, many of these are fairly common,
and they tend to trip up new C# developers.
| | 00:22 | Don't feel bad if this happens to you.
| | 00:24 | I personally assure you that I myself
have committed every single one of the
| | 00:28 | issues I am about to show you.
| | 00:30 | So I've got my CompileIssues sample
project opened, and what I am going to do is
| | 00:33 | walk through each one of these issues
and show you why each one is a problem.
| | 00:38 | So I am going to start with issue number one.
| | 00:40 | Let me uncomment this line of code,
and we'll save. And we've got a problem.
| | 00:45 | In fact, let me hit the F6 button to
try to build, so we can see what the
| | 00:48 | problem exactly is, and I
will scroll that code into view.
| | 00:52 | We can see here down in
the error list it, says, ah!
| | 00:54 | There is a semicolon expected.
| | 00:57 | Well, a semicolon is expected at
the end of every line of C# code.
| | 01:02 | If you're coming from a language like
JavaScript where semicolons are optional,
| | 01:06 | you need to realize that
in C#, that's not the case.
| | 01:08 | You do have to have a semicolon that
terminates every single one of your statements.
| | 01:13 | Double-click on the error, and it
takes us right to that point in the code.
| | 01:17 | We can put in our semicolon, and save,
and then we can build, and now everything
| | 01:21 | is all right again.
| | 01:22 | Now we're getting a bit of a warning
here that says that the myString variable
| | 01:26 | is assigned, but it's never used,
but let's just ignore that for the moment.
| | 01:30 | Go down to issue number two.
| | 01:32 | So issue number two, I am going to
uncomment this line of code, and once again we
| | 01:35 | get a whole bunch of errors.
| | 01:38 | Sometimes it's tempting to try to look
for the error that's the simplest to fix
| | 01:42 | and try to fix it that way.
| | 01:43 | In fact, if you look in the error list,
you'll see that there's a bunch of errors.
| | 01:46 | One of them says "; expected,"
One of them says ") expected."
| | 01:50 | So you might be tempted to just
jump to that line and try to like put a
| | 01:53 | semicolon in to fix things;
| | 01:55 | that's actually the wrong thing to do here.
| | 01:57 | What I suggest you do is start with
the topmost error, because sometimes when
| | 02:01 | you fix the topmost error, that will
fix all the errors below it. And if you
| | 02:06 | look really closely at this line,
you'll notice that the problem is that I
| | 02:10 | didn't close off the string using
double quotes. And sure enough, once I do that,
| | 02:16 | all the other errors go away.
| | 02:18 | Before you try to figure out which
is the easiest problem to solve, try to
| | 02:22 | figure out what the actual error is,
because now you can see that the compiler
| | 02:25 | is saying, oh yeah, there is a semicolon,
and oh yeah, there's the parentheses.
| | 02:29 | It just couldn't see them before,
because it thought they were part of the
| | 02:32 | string, Hello World.
| | 02:35 | In the next issue, I'm
going to use an ArrayList.
| | 02:37 | If you watched the section on
collections, you know what ArrayLists are.
| | 02:41 | They are a type of
collection that works like an array.
| | 02:44 | I am going to uncomment this line,
and sure enough, we've got problems.
| | 02:48 | If we look in the error list, it
says, "The type or namespace name
| | 02:53 | ArrayList could not be found (are
you missing a using directive or an
| | 02:57 | assembly reference?)."
| | 02:58 | That's just a very long-winded way of the
C# compiler saying, I don't know what that is.
| | 03:03 | And there's also a visual cue.
| | 03:05 | You'll notice that objects that
are recognized by the C# compiler are
| | 03:09 | highlighted in a certain color,
like the console object right here.
| | 03:13 | Now ordinarily, ArrayList would be
highlighted as well, and it's not, and that's
| | 03:17 | your first clue that something is
wrong, along with this giant red squiggle
| | 03:20 | underneath it that gives you the error.
| | 03:23 | It turns out that the problem is I
have not included the right namespace in
| | 03:27 | order to use ArrayLists.
| | 03:29 | So I have to scroll to the top of the
file, and sure enough, I'm using the
| | 03:34 | System.Collections.Generic namespace,
but ArrayLists are contained in the
| | 03:39 | System.Collections namespace.
| | 03:42 | So I have to say using
System.Collections. And when I put that using statement
| | 03:49 | in, you can see that the problem goes away.
| | 03:53 | Let's scroll back down to where that
code is, and you'll see now that the
| | 03:57 | ArrayList object is highlighted in light
blue the same way that the console is,
| | 04:02 | which means that the C#
compiler is recognizing it. All right!
| | 04:06 | Let's move on down to the next issue.
| | 04:08 | I am going to uncomment
these lines of code right here.
| | 04:12 | I am going to save, and you see
that we're getting a complaint that a
| | 04:22 | curly brace is expected.
| | 04:24 | The curly brace is actually expected
way down at the end of the program. Well,
| | 04:28 | clearly something is pretty wrong here.
| | 04:31 | And if we scroll back up to where the
error actually is, you'll notice that
| | 04:36 | I've got my open curly brace here and a
closing curly brace here, and those seem to match up.
| | 04:42 | You can see that when I put the
cursor next to the curly brace, the IDE
| | 04:46 | highlights the two braces
to show me they match.
| | 04:48 | But the problem is that I have
actually got an extra one all the way over
| | 04:51 | here on the end of the for statement,
and that's causing the compiler to
| | 04:56 | think that all the rest of the code
following that line is contained in an
| | 05:01 | unclosed curly brace block.
| | 05:03 | Once I get rid of that extra curly brace
and I save and I hit F6, you can see
| | 05:09 | that that error goes away.
| | 05:11 | So the lesson here is, indentation does
not necessarily mean what blocks are.
| | 05:17 | You have to put braces so they match each other.
| | 05:20 | Just because you put one brace up here
and another brace in another line down
| | 05:23 | there, does not mean that those make a block.
| | 05:26 | You have to make sure that you have
the same number of closing braces as you
| | 05:30 | have opening braces; otherwise, you're
going to get weird errors like that.
| | 05:35 | Let's move on to issue number five.
| | 05:37 | I am going to uncomment this string
right here, I am going to save, and I am
| | 05:41 | going to get a nice big red squiggle.
| | 05:43 | It says down here in the error list:
| | 05:45 | "Too many characters in character
literal" and "Cannot implicitly convert
| | 05:50 | type 'char' to 'string'."
| | 05:53 | What's going on here?
| | 05:54 | I've got my quotes.
| | 05:55 | I've got the string defined.
The problem here is that you can't use single
| | 06:00 | quotes to define a string in C#;
| | 06:03 | you must use double quotes.
| | 06:05 | The single quotes are for individual
characters. And so you see that when I put
| | 06:12 | the single quotes into double
quotes, the error goes away.
| | 06:16 | Now, I am getting another warning that
says that that string is not used, but
| | 06:18 | don't worry about that for now.
| | 06:20 | Scroll down to the next issue.
| | 06:21 | I'm going to uncomment these two lines.
| | 06:29 | So I have an integer array of values
and it's called myarray = 0, 1, 2, 3, 4,
| | 06:36 | so we've got 5 items in the array,
and then I am trying to set the array item at
| | 06:41 | index 2 to be 10, and I am getting an error.
| | 06:44 | It says "'myarray' is a 'variable',
but it is used like a 'method'" and the
| | 06:49 | problem here is that you don't use
parentheses to index into arrays; you
| | 06:54 | use square brackets.
| | 06:58 | Parentheses are used for calling function;
brackets are used to index into arrays.
| | 07:05 | You can see that once I change the
brackets, everything is fine. All right!
| | 07:08 | Let's go on to the next issue.
| | 07:10 | I am going to uncomment this call to
Console.WriteLine, and then I get an error.
| | 07:15 | It says, "'System.Console' does not
contain definition for 'Writeline'."
| | 07:19 | What are you talking about? Sure it does.
| | 07:20 | I've been using
Writeline throughout this course.
| | 07:23 | There's a function there called Writeline.
| | 07:24 | I know that there is. In fact, I used it
probably up here earlier. See, there it is!
| | 07:28 | And then I realized, oh, wait a minute!
| | 07:29 | No, there is a capitalization problem in there.
| | 07:33 | That actually has to be a capital L.
That's because C# is a case-sensitive
| | 07:39 | language; case matters.
| | 07:41 | This is something you'll run into
probably at least once when you're
| | 07:44 | writing your C# code.
| | 07:45 | You need to make sure that the cases
match. That's true of variables.
| | 07:49 | It's true of function names.
| | 07:50 | It's true of almost any type of
declaration that you make in C#.
| | 07:55 | Let's move on to issue number 8.
| | 07:58 | In issue number 8 I have
got three lines of code.
| | 08:01 | I've got an integer variable that's set to 2,500,
| | 08:04 | I've got a floating-point variable
that's set to 35.895, and then I'm trying
| | 08:12 | to set the value of f into the
value of i. Now, I've got two different
| | 08:18 | problems going on here.
| | 08:19 | First, "A local variable named 'i'
cannot be declared in this scope, because it
| | 08:23 | would give a different meaning to 'i',
which is already used in a 'child' scope
| | 08:26 | to denote something else."
| | 08:28 | That's a very, very long-winded way of
saying, you know what, I've already used
| | 08:32 | i somewhere else in this code block.
| | 08:34 | So if I scroll back up, there it is.
| | 08:37 | I've already used the i variable in this for loop.
| | 08:41 | So it's not going to let
me use it again down here.
| | 08:44 | No problem. I will just simply call
this i1, and I will call that one i1.
| | 08:51 | I've got another problem. The problem here is--
let's look at the error list--"Cannot
| | 08:55 | implicitly convert type 'float' to 'int'.
| | 08:58 | An explicit conversion exists (are
you missing a cast?)." Yes, I am.
| | 09:04 | Remember, you can't implicitly cast a variable
that is of a larger size into a smaller size.
| | 09:11 | You have to explicitly tell the
compiler that you're doing that.
| | 09:14 | So what I need to do to convert a float
into an int, I have to put the word int
| | 09:19 | in parentheses. And what this
tells the compiler is, hey compiler!
| | 09:23 | Treat that floating-point number as if
it were an integer, which will let me
| | 09:27 | assign it to another variable that is
of that same type--in this case integer.
| | 09:32 | And you can see when I put that cast in front
of the F, everything goes away, and we're fine.
| | 09:37 | Next issue, issue number 9, I am
going to uncomment these lines.
| | 09:41 | I've got two integer variables: one
named a, one named b. And then I've got an
| | 09:45 | if statement, if (a = b) then
we're going to write out, yup!
| | 09:49 | They're equal numbers, and no
sooner do I do that, then oops!
| | 09:52 | I get an error, and it says, "Cannot
implicitly convert type 'int' to 'bool'."
| | 09:57 | What's the problem here?
| | 09:58 | I am not trying to convert anything to anything.
| | 10:01 | Well, remember that inside if statements
what you're checking for is a Boolean condition.
| | 10:06 | That's how the if statement knows to
execute. And the problem here is that I'm
| | 10:10 | not using double equals signs.
| | 10:12 | I'm using the assignment operator,
not the equality check operator.
| | 10:16 | So once I change this to the
equality check operator, the error goes away,
| | 10:20 | and everything is fine.
| | 10:22 | One more issue that I want to show you,
and you'll run into this, and sometimes
| | 10:27 | it can be pretty
confusing as to what's going on.
| | 10:29 | I am going to uncomment this entire function.
| | 10:31 | I've got a function here called func,
and it takes an integer variable and if
| | 10:38 | that integer parameter is
greater than 0, then it returns 0.
| | 10:43 | If that parameter is less than 0, it returns -1.
| | 10:46 | But I'm getting an error.
| | 10:48 | It says, "CompileIssues.Program.func:
not all code paths return a value."
| | 10:55 | The problem here is that I've declared
this function to return an integer value,
| | 11:00 | and I am returning an integer value
here and returning an integer value here.
| | 11:05 | But what happens if the
parameter a is equal to 0?
| | 11:08 | Well, there's no path in
here that returns a number.
| | 11:12 | I have to make sure that if my function
is going to return a value, then all of
| | 11:16 | the possible code paths that it can
take have a return statement in there.
| | 11:20 | There's a couple of ways I can fix this.
| | 11:22 | I could put in an if case for a is
double equal to 0, but since that's
| | 11:27 | the only case left, and the function
would have returned by now if any other
| | 11:31 | case have been encountered, I can
just simply say return whatever else.
| | 11:35 | I can say return 100, or I can return
1,000, or I can return whatever I want as
| | 11:40 | long as it is a valid return type.
| | 11:44 | Those are 10 of the most common
compilation issues that you'll probably run
| | 11:48 | across in your C# coding.
| | 11:50 | Next, we're going to take a look at
how to use the debugger to look at
| | 11:53 | code while it's running.
| | Collapse this transcript |
| Setting breakpoints and examining code| 00:00 | As useful as it is to be using the
console and the Console.WriteLine methods to
| | 00:06 | see what's going on inside our
application while it's running,
| | 00:09 | there's really no good substitute for
using a good debugger which you can use to
| | 00:14 | examine the code while it's actually
running. And the debugger allows you to do
| | 00:18 | things like place breakpoints in your
code, examine the code, examine variables,
| | 00:23 | change things while it's running, and so on.
| | 00:26 | If you've done any kind of
programming in other environments, like, say,
| | 00:29 | JavaScript using either Firebug or
the WebKit Developer tools or coding
| | 00:34 | environments like C++ or Java, you
might be familiar with using a debugger.
| | 00:39 | If not, don't worry about it.
| | 00:40 | I am going to show you how to use the
debugger that's contained here in the free
| | 00:44 | version of Visual C# Express.
| | 00:47 | I am just going to use the existing
example that we've already got from the
| | 00:51 | section that we did on reading and
writing file data, so I've got that example
| | 00:57 | back open in my editor here.
| | 01:00 | Take a quick look. Under the Debug menu,
| | 01:03 | you'll see that there are a
couple of options related to debugging.
| | 01:07 | There's the Start Debugging option,
which is this option right here on F5,
| | 01:10 | and that's actually how I've been running
our examples each time we've tried them out.
| | 01:14 | I just hit F5 and that
starts the debugging process.
| | 01:18 | You can also start an application
without debugging by doing the Ctrl+F5. But if
| | 01:22 | you want to actually have debugging
information, you'd use the F5 version.
| | 01:25 | There are also things like Step Into
and Step Over, and things like Toggle
| | 01:30 | Breakpoint, and we are going to
see how each one of these works.
| | 01:33 | So let me close this menu. And the
first thing I am going to do is show you how
| | 01:38 | to place a breakpoint.
| | 01:40 | Here we have our Main function, and the
Main function is going to be the entry
| | 01:45 | point into our
application from the .NET Framework.
| | 01:48 | The .NET Framework is going to find this
function and then call it to start our program up.
| | 01:51 | So the first thing I am going to do is
find the first place where I can put a
| | 01:56 | breakpoint. And it looks like this line
right here, line 14 is where our program
| | 02:00 | actually does something.
| | 02:02 | So way over here in the left-hand side
of the gutter, next to the line numbers, I
| | 02:06 | am going to click, and you see that
when I click, a couple of things happen.
| | 02:10 | First, this little red circle shows up.
| | 02:13 | That little red circle indicates that
it is a breakpoint, and you'll notice that
| | 02:17 | when I place that breakpoint, all the
executable code that gets associated with
| | 02:22 | that line--in this case, it's line 14
and 15, because I have one statement
| | 02:27 | that's spanning multiple lines--gets
outlined in red. And it indicates to me
| | 02:32 | that that is a breakpoint.
| | 02:34 | A breakpoint is a point in the
program where when you're running the
| | 02:37 | application, the debugger will stop
execution right before it's about to
| | 02:42 | execute that statement.
| | 02:44 | So let's go ahead and
start debugging the program.
| | 02:47 | Open the Debug menu. I am going to choose
Start Debugging, or you can just press F5.
| | 02:54 | Now when I do that, you saw the Console
window kind of momentarily come up there
| | 02:58 | and then disappear behind the IDE.
And now you can see this little yellow arrow
| | 03:03 | inside that little breakpoint there,
and it shows me where the current statement is.
| | 03:08 | The breakpoint that was red is now
outlined in yellow, and you can see that
| | 03:13 | we've got a couple of other
windows that have shown up.
| | 03:15 | Down here in the bottom, on the left-
hand side, we have the Locals window.
| | 03:21 | We also have something called the Watch window.
| | 03:24 | The Locals window shows me all of
the local variables that are currently
| | 03:29 | within the current scope.
| | 03:31 | So inside the Main function, I can
see all the local variables that I can
| | 03:35 | currently have access to.
| | 03:37 | Over here in the Call Stack, this shows
me all of the functions that have been
| | 03:41 | called leading up to this point.
| | 03:43 | Now right now we are in the main function.
| | 03:46 | I have only got two items on the Call Stack.
| | 03:48 | I have got External Code which is the
.NET Framework's execution engine, and
| | 03:52 | then I've got the ReadingWritingData.
exe!ReadingWritingData.Program.Main, so
| | 03:58 | that's the function that I'm in.
| | 04:00 | so ReadingWritingData.exe! that's my program.
| | 04:03 | ReadingWritingData is my
namespace. Program is the class.
| | 04:06 | That's this program right up here.
| | 04:08 | Main is the function, and it says I am
on line 14. And sure enough, if I look
| | 04:13 | over at the little arrow, yes, I am on line 14.
| | 04:17 | The other thing that happens is that
this little Debug toolbar showed up in my
| | 04:21 | toolbars up here. And I have got
buttons for Continuing, so if I hit F5 right
| | 04:25 | now, the program will just continue to
run until it reaches the next breakpoint.
| | 04:29 | Or I can stop debugging which will
stop the application, or I can restart.
| | 04:34 | I can have the program go back to the beginning.
| | 04:36 | I can click on this little yellow arrow
here to show me what the next statement
| | 04:39 | is going to be, and that's where
the yellow arrow right over here is.
| | 04:42 | I've also got these three icons for Step
Into, Step Over, and Step Out, and we'll
| | 04:49 | take a look at what each one of these is.
| | 04:51 | To step over this code, I can
simply choose the Step Over function.
| | 04:56 | That will cause the current statement,
the one that's highlighted right here, to
| | 04:59 | execute. And if you look down here in
the Locals window, you will notice the
| | 05:03 | filePath variable right now is null.
| | 05:07 | There is no value assigned to it.
| | 05:09 | Watch what happens when we step over that line.
| | 05:13 | First, the little yellow arrow goes to
line 18, because that's where the next
| | 05:18 | line of executable code is.
| | 05:20 | The second thing that happens is, if
you look down in the Locals window, the
| | 05:24 | filePath variable now has this string
in it, and it has a path to the example
| | 05:30 | file.txt. And you notice also it's red,
and the reason it's red is because the C#
| | 05:36 | debugger is highlighting the
local variable that changed.
| | 05:41 | After I step again, it's going to
stop being red, because it's not going to
| | 05:45 | change after that point.
| | 05:46 | I can scroll down a little bit here.
| | 05:49 | Now if I wanted to, I actually could
just simply change the value that's in
| | 05:53 | this local variable.
| | 05:54 | I can just double-click on
it and say, you know what?
| | 05:56 | I don't want it to be called
examplefile.txt; I want it to be
| | 05:59 | called joesfile.txt.
| | 06:05 | I just changed the contents of that
variable while the application is still running.
| | 06:10 | So now this line of code right here is
going to check to see if the file exists,
| | 06:14 | and it does not. So when I step over
that statement, we'll see that the brace
| | 06:20 | gets highlighted, and I step again,
and now we step into the if statement.
| | 06:25 | So now we are going to create
that file and set its contents.
| | 06:30 | And once again, I can step over this,
and you can see now that this content
| | 06:34 | variable has changed.
| | 06:36 | So I can also do things like
hover over using the mouse.
| | 06:40 | I can hover over things that are in the code.
| | 06:42 | For example, if I hover over the
Environment.NewLine statement right here, you
| | 06:46 | will see I get this little pop-up window
that says what the new line's value is.
| | 06:50 | And you can see that it's \r\n. Or I
can hover over this local variable, and it
| | 06:55 | shows me what the contents
of that local variable is.
| | 06:58 | I can also hover over things that
are built into the .NET Framework.
| | 07:01 | I can hover over the file class, for example.
| | 07:03 | When I hover over the file class it
shows me that it's of type System.I/O.File,
| | 07:09 | and I can click on this little
expander here, and it shows me all the things
| | 07:13 | that are inside that file class.
| | 07:16 | Now, it's a built-in class, so it's
not going to show me very much, because
| | 07:19 | it's in native code.
| | 07:20 | But I can now just use my debugger to
step through this code, and I can watch
| | 07:25 | the application as it runs.
| | 07:27 | You will see that variables are changing.
| | 07:30 | I can change the value of variables and so on.
| | 07:33 | If I've gotten tired of just stepping
through this, I can just go ahead and hit
| | 07:37 | the little green arrow, which will
cause the application to run, and we can see
| | 07:42 | that the application is now running.
| | 07:43 | And if I go ahead and hit the Return
button, the application will stop, the
| | 07:48 | debugger stops, and I am
dumped back into my text editor.
| | 07:51 | Let's make a slight
modification to this application.
| | 07:54 | What I'm going to do is make a function,
and I am going to make a function down
| | 07:59 | here called static void
ReadAndListContents(). And it's going to read and list
| | 08:13 | all the contents of the file.
So basically, I am going to copy these lines of
| | 08:17 | code right here, take them out of
the Main function, and put them into a
| | 08:22 | function And I am doing this because
I want to show you how the Step Into
| | 08:26 | functionality works.
| | 08:27 | I'll just get rid of that comment right there.
| | 08:30 | I need to pass in the filePath,
and I also need to call that function,
| | 08:37 | so we'll call ReadAndListContents with
the filePath. And just to isolate this,
| | 08:47 | we'll take out this code right here,
so that we only have one piece of code,
| | 08:52 | that's ReadingAndListingTheFileContents.
| | 08:55 | What I am going to do is run the
application again, and it's going to stop at
| | 09:00 | this breakpoint right away.
| | 09:02 | This time I am going to start at
using this little green arrow right here.
| | 09:06 | You can see that the breakpoint got hit.
| | 09:08 | What I am going to do now is scroll
down and I am going to place a breakpoint
| | 09:12 | on this function call.
| | 09:13 | So I just click there to place another
breakpoint, and now I'm going to hit the
| | 09:18 | little green arrow again, which is going
to continue on to the next breakpoint.
| | 09:22 | The application ran until
it got to this breakpoint.
| | 09:25 | Now I can use the Step Into function,
and that's this icon right here.
| | 09:31 | If I wanted to just simply execute
this function without stepping into it, I
| | 09:34 | could use the Step Over.
| | 09:35 | That doesn't mean skip over the function;
| | 09:38 | it means execute it but don't go inside.
Just do whatever the work it does, and
| | 09:43 | then go on to the statement at
the level where I currently am.
| | 09:46 | So if I stepped right now, the next
statement would be this Console.ReadLine.
| | 09:49 | But if I do a Step In, I will
actually step into that function.
| | 09:55 | And now I can do Step Over and Step
Over again, and you can see now that the
| | 10:00 | current line, as indicated with this
little yellow arrow right here, is inside the
| | 10:04 | ReadAndListContents.
| | 10:06 | I could just simply keep on
stepping and stepping and stepping and
| | 10:09 | going through these foreach statements and
so on, or I could use the Step Out function.
| | 10:15 | If I click on Step Out, the execution
is going to continue to the end of this
| | 10:19 | function and it's going to put me
back into where the calling context was.
| | 10:23 | If I click Step Out, now I'm back out
here where ReadAndListContents was called,
| | 10:30 | but now the function has finished
executing and if I step again, I'll go on to
| | 10:34 | the next statement, which
is the Console.ReadLine.
| | 10:38 | That's a pretty quick
introduction to using the debugger.
| | 10:41 | The nice thing about the debugger is
that it allows you to slow down the
| | 10:44 | program's execution so that you
can see things as they are happening.
| | 10:47 | And as you saw, we were able to
place breakpoints and examine variables.
| | 10:51 | We were able to change
the contents of variables.
| | 10:54 | We were able to step into and out of functions.
| | 10:56 | The debugger really will become your
best friend as you're writing your code
| | 11:00 | because it makes debugging of
your applications so much easier.
| | Collapse this transcript |
| Using the Debug class| 00:00 | Throughout this course I've been
using the console window to write out
| | 00:03 | debugging and other diagnostic
information so that we can see what's going on
| | 00:08 | inside the application.
| | 00:09 | For examples like this, that's all well
and good, but when you write your real
| | 00:12 | applications, if you're writing a
console application, you probably don't want
| | 00:15 | to have it littered with debugging
information that your users are going to see.
| | 00:19 | Or if you're writing an application
that doesn't use the console window at all,
| | 00:22 | you're going to need to have some
other way to get that output visible to you
| | 00:26 | while you're debugging your app.
| | 00:28 | The way that we are going to do this
in this particular example is by using
| | 00:31 | the System.Diagnostics namespace, which gives
us access to something called the debug class.
| | 00:38 | The debug class gives us a way for
logging debugging information in a way that
| | 00:42 | we can see it which doesn't interfere
with the actual output of the program.
| | 00:48 | To use the debug class, I am
going to do a couple of things.
| | 00:51 | See, on line 16 the System.
Diagnostics namespace. This gives me access to
| | 00:57 | something called the debug class,
which gives us a bunch of features that are
| | 01:00 | similar to what we've been
using the console window for--
| | 01:03 | WriteLine statement and a few other
things that we'll take a closer look at.
| | 01:07 | The debug class is going to log all
this information to a place called the
| | 01:11 | output window, and the output window
is going to show up here in the IDE
| | 01:15 | when we make it visible.
| | 01:17 | To use the output window, there is a
couple of things you are going to have to do.
| | 01:20 | First, under the Tools menu, go down to
the Settings submenu and make sure that
| | 01:25 | the Expert Settings option is checked.
| | 01:27 | Once you've done that, under the View
menu, there will be an option for Output,
| | 01:32 | and when you choose Output this little
output window will show up here in your IDE.
| | 01:37 | Don't worry about the Show output from
option just yet. Tight now it's empty,
| | 01:40 | but that will be filled in for us.
| | 01:43 | If you are a sharp-eyed reader, you'll
notice that I'm using pretty much the
| | 01:46 | same code that we used in the Reading
and Writing Data Files example, although
| | 01:51 | I've re-organized it a little
bit to use functions and so on.
| | 01:55 | What we are going to do now is
first build the application, so hit F6.
| | 02:01 | And you'll see that down in the output
window, a whole bunch of information was
| | 02:05 | logged for us by the IDE.
| | 02:07 | It says that the build was started,
and then there is a line that says,
| | 02:09 | hey, Build 1 succeeded.
| | 02:11 | So everything looks pretty good.
| | 02:13 | Our code can also use this same output
window to log debugging information, and
| | 02:18 | the way that we are going to do
that is by using the debug class.
| | 02:21 | Go ahead and scroll down and
see how the debug class works.
| | 02:25 | This code probably looks familiar to you if
you watched the earlier example on using files.
| | 02:30 | I'm not going to focus too much on that.
| | 02:32 | What I am going to focus on instead is
the information that I've put into the
| | 02:35 | file to help with debugging.
| | 02:37 | Here's a debug class call. And you
will notice that the debug object has a
| | 02:42 | function called WriteLine, which
works pretty much the same way that the
| | 02:47 | console's WriteLine object works as well.
| | 02:50 | Only instead of sending output to the
Console window, this is going to write
| | 02:54 | information out into this
output window down here.
| | 02:58 | Here I am write-lining out some piece
of information that the file was created,
| | 03:02 | and so on and so forth,
and we do the same thing down here.
| | 03:06 | A couple of other features, though.
| | 03:07 | There is a assert function call,
and assert basically makes sure that the
| | 03:13 | Boolean condition supplied in here is true.
| | 03:17 | If it ever evaluates to false, the
debugger is going to pop up and say, hey,
| | 03:21 | something went horribly wrong in your program.
| | 03:23 | You might want to take a look at it.
And we'll see an example of that in a little bit.
| | 03:26 | We also have this here, Debug Indent
and Debug Unindent, and that will help us
| | 03:32 | make our debug log output more visible
in the output window below, which we'll
| | 03:37 | see in just a moment.
| | 03:39 | Let's go ahead and run this
program, and we'll see what happens.
| | 03:43 | Let's just take a quick refresher of the code.
| | 03:46 | You can see that when the code starts
| | 03:47 | we have a string variable that holds a
filePath, and we are going to create a data file.
| | 03:52 | We are going to write
some information out to it,
| | 03:54 | and then I am going to read the
contents back in. And all that's going to be
| | 03:58 | happening in these functions down here.
| | 04:00 | We have a function for creating the
file, we have a function for writing the
| | 04:03 | file content out, and then we have a
function for reading the content back in.
| | 04:09 | So the last thing I want to point out
before we run this is that unlike the
| | 04:12 | console window, the debug object
has a special version of WriteLine.
| | 04:17 | It's called WriteLineIf.
| | 04:19 | What you do here is you supply a
Boolean expression. If this expression
| | 04:24 | evaluates to true, then the WriteLine
happens; otherwise the WriteLine doesn't happen.
| | 04:29 | In this particular case, we are saying
Debug.WriteLineIf the contents array
| | 04:34 | length is greater than 2.
| | 04:37 | Well, if that length of that array
is more than 2, then this particular
| | 04:41 | WriteLine will happen; otherwise it won't.
So let's go ahead and run this example.
| | 04:49 | We ran the file, and we added a whole
bunch of content to the file, so let's
| | 04:53 | go ahead and hit Return to exit, and let's
go examine the output in the output window.
| | 05:00 | The first thing you will notice is
there is a whole bunch of output messages
| | 05:03 | that were put here by the .NET Framework.
| | 05:06 | You don't really need to
pay attention to any of these.
| | 05:08 | These are messages that the debug
version of .NET Framework is sending out for
| | 05:13 | you to look at as a programmer,
but for now, we are just going to ignore that.
| | 05:16 | What we are going to do is look for
our first examples of debug output, and
| | 05:20 | they are right here.
| | 05:21 | For example, we have Writing
File Data, File Data Written,
| | 05:26 | The file has more than two lines.
| | 05:28 | Well, where did those come from?
| | 05:29 | Well, if we scroll down in our content,
we can see right here, this did not
| | 05:35 | execute, because the file already
exists, but if the file hadn't existed,
| | 05:39 | we would have called the WriteLine function
for creating the file with content whatever.
| | 05:43 | However, when we write the file data
out, you'll notice that the WritingFile
| | 05:48 | Data string got written out,
and because it's indented, right here you can see
| | 05:53 | that there is a little bit of a tab
space in here, which makes the debug
| | 05:56 | information a little bit easier to read.
| | 05:59 | Down here we do the same thing. After
the file's data has been written, we have
| | 06:03 | a debug output statement that says the
file data has been written, and that's
| | 06:07 | also indented. And because the
contents of that file had more than two lines,
| | 06:13 | you can see that this
WriteLineIf statement executed.
| | 06:17 | Let's do one more example.
| | 06:20 | Let's see if we can get this
assert to trigger right here.
| | 06:26 | What we are going to do is pass in an
empty string content to write to the file.
| | 06:32 | I've decided that here in my application
that anyone who calls this function has
| | 06:37 | to provide string content that's not empty.
| | 06:41 | If I pass in an empty string, I want my
program to raise a warning message and
| | 06:46 | say that someone has tried to do
something that I don't approve of. And the
| | 06:50 | great thing about these debug
messages is that when you build the release
| | 06:54 | version of your code, none
of this stuff gets included;
| | 06:57 | only the debug version of your
application will contain these debug calls.
| | 07:04 | So let's go back up into the code here.
| | 07:05 | I'm going to uncomment this call to
WriteFileData, and I am going to pass in an
| | 07:13 | empty string. And that's going
to cause that assert to pop up.
| | 07:18 | Let's see what happens when I try this.
| | 07:20 | I am going to run this.
| | 07:22 | When I ran this, the Assertion
Failed dialog message comes up.
| | 07:27 | So here the title says Assertion Failed,
and then I have some options. Do I want
| | 07:30 | to abort or retry or ignore?
| | 07:33 | Now this is a non-fatal assert, so I can
just go ahead and ignore it if I want to.
| | 07:38 | But for now what I am going to do
is click Abort, which will cause the
| | 07:42 | application to stop.
| | 07:43 | I can see where that
assert was. It's down in here.
| | 07:47 | You notice that there wasn't a whole
lot of helpful information that came up in
| | 07:51 | that Assert box, just a big stack of
messages that says, hey, here's the
| | 07:55 | function where things went wrong.
| | 07:57 | So I can include a message in this assert.
| | 08:01 | I can say, "Tried to call
WriteFileData with an empty string."
| | 08:10 | This version of the Assert
function will not only pop up the dialog;
| | 08:15 | it will give me a nice easy-to-understand
message, so I can see what's going wrong.
| | 08:19 | Let's try that one more time. And you
can see that this time, next to that
| | 08:24 | little red error message that says, Tried
to call WriteFileData with an empty string,
| | 08:28 | that's the message that I put into
my Assert box, and it shows me all the
| | 08:32 | functions that got me to the current place.
| | 08:35 | So right here at the top it
says, at Program.WriteFileData.
| | 08:38 | That's where the assertion happened.
And you can see that we got there by
| | 08:42 | calling through Main, and then
we came in via the .NET Framework.
| | 08:46 | These are all the .NET Framework
functions right here. Bt it shows me how we
| | 08:49 | got to where the assert is.
| | 08:51 | So I am going to click Abort. And then
at this point I would go back and I would
| | 08:56 | try to figure out, okay, who is calling
WriteFileData, who is doing it with an
| | 09:00 | empty string, and so on?
| | 09:02 | This is how you can use the debug class
to add some extra debugging information
| | 09:08 | right into the IDE while you
are debugging your application.
| | Collapse this transcript |
|
|
ConclusionGoodbye| 00:00 | Well, that brings us to the end of
C# Essential Training, and I want to thank
| | 00:04 | you for joining me as we explored
the basic concepts of the C# language.
| | 00:08 | You are probably wondering where
you should go next, and I have a few
| | 00:11 | recommendations for you.
| | 00:12 | Spend some time exploring the online
documentation for the C# language and .NET
| | 00:17 | Framework on the Microsoft
Development Network web site at msdn.microsoft.com.
| | 00:23 | This is a very good reference
resource for learning more about many of
| | 00:26 | the objects, classes, and language features
that we were introduced to in this course.
| | 00:31 | Since C# is the foundational language
for other Microsoft frameworks, such as
| | 00:36 | Silverlight, Windows Phone, and ASP.NET,
| | 00:39 | take a look at some of the other
programming resources in the lynda.com Online
| | 00:44 | Training Library, such as
Objective-C or JavaScript Essential Training.
| | 00:48 | Seeing how other languages approach
similar problems and situations can
| | 00:53 | significantly increase your
understanding of how each language has its own
| | 00:56 | benefits and drawbacks, and will broaden your
understanding of the discipline of programming.
| | 01:01 | Finally, go back to some of the examples
in this course and try some experiments.
| | 01:05 | The more practice you have with the
language, the better a C# programmer you will be.
| | 01:09 | Good luck with your C# coding!
| | Collapse this transcript |
|
|