Assignment Operations: Operations where a value is assigned or stored in a variable.
variableName assignmentOperator expression
variableName is the name of the variable that will receive/store the value.
assignmentOperator is one of the following:
= Equals (Assign)
+= Plus-Equals and -= Minus-Equals
*= Multiply-Equals and /= Divide-Equals and %= Modulus-Equals
expression is any valid C# expression matching the variable's data type
Add a semicolon to make it an assignment statement
total = price * quantity;
Expressions
An Expression is any combination of
literal values,
variable names,
operators, and/or
method calls (where the method returns a value).
Expressions are evaluated at run-time.
When an expression is processed by the computer, a single value is produced.
Namespace Declaration
namespaceName
{
// Classes, enumerations, or other programmer-defined data types
}
A Namespace Declaration groups programmer-defined data types where
The Name of the namespace can be one or more dot-separated names. For example, the following are all valid names for namespaces. System System.Collections MyGame MyGame.GameRules
Using Statement
using NamespaceName;
Allows access to all the data types in referenced namespace
Typically placed at the beginning of a file
using Alias = NamespaceName.DataTypeName;
Create an alternate name for a data type (a class, enum, interface, etc.)
usingstatic NamespaceName.DataTypeName;
Allows us to use the name of static members without the class name
Classes and Class Members
Class Definition
Field Declarations
Property Declarations
Methods
Constructors
Classes and Class Members
A class is a "blue print" for creating objects. A class describes
MethodName is the programmer-defined name of the method,
argumentList is a comma-separated list of values that correspond to the parameters of the method declaration,
When called from outside the class, use
ClassName for static methods, ObjectName for instance methods
The Member Access Operator - . - after ClassName/ObjectName
When called from inside the class,
ClassName/ObjectName can be omitted.
this Keyword
Only used with instance (non-static) members of the class within which it is used
The this keyword is implied, but is optional
Display("Some Text")
is interpreted as
this.Display("Some Text")
If-Else
if(conditionalExpression)
statementOrStatementBlock // true sideelse
statementOrStatementBlock // false side
The if-else provides alternate paths of logic, where
conditionalExpression is an expression whose ultimate data type is a bool.
statementOrStatementBlock is either a single statement or a single statement block (zero or more statements inside curly braces - { }).
Immediately after the if: will run if conditionalStatement results in a true
Immediately after the else: will run if conditionalStatement results in a false
The else statementOrStatementBlock portion is optional.
Switch-Case
switch(cardinalExpression)
{
case matchingExpression1:
statementOrStatementBlock
break;
case matchingExpression2:
statementOrStatementBlock
break;
// ...additional case statements...default:
statementOrStatementBlock
break;
}
Switch-Case (cont.)
The switch provides alternate paths of logic, where
cardinalExpression is an expression that produces a single value of any primitive data type (int, double, char, string or an enum).
Each matchingExpression is a constant value whose data type matches the data type of the cardinalExpression. A match is determined by the value of the cardinalExpression being equal to the matchingExpression. The break indicates the end of the path of logic for the matching expression.
statementOrStatementBlock is either a single statement or a single statement block (zero or more statements inside curly braces - { }).
The default block will execute if cardinalExpression did not match any of the listed matching expressions.
"An interface defines a contract. Any class or struct that implements that contract must provide an implementation of the members defined in the interface." (source)
[accessModifier] interfaceTypeName
{
// Interface members
}
[accessModifier] is either public or internal. If no access modifier is provided, then the default modifier is internal
TypeName is the programmer-defined name for the interface type
Interfaces
Interface members can include the signatures for
Properties - Identify the presence of a getter and/or optional setter method
Methods - No body is specified for the method (pre C# 8)
propertyType PropertyName { get; [set;] }
returnType MethodName(parameterList);
There are no access modifiers on interface members.
Interface Implementations
You cannot directly instantiate an interface.
You can reference an object by its interface type.
Classes and structs can implement many interfaces.
Data Types and Inheritance
Inheritance can be applied to classes, interfaces, and enumerations
A class can only inherit from one other class, but may implement multiple interfaces
An interface can only inherit from other interfaces
An enum can only inherit from the integer-based types int, short, long
Data Types and Inheritance
[accessModifier] typeKeyword DerivedTypeName [: BaseType]
{
// Members
}
Inheritance "builds on" a base type data type where
[accessModifier] is either public or internal. If no access modifier is provided, then the default modifier is internal
typeKeyword is either class, enum or interface
DerivedTypeName is the programmer-supplied name for the data type that inherits from the BaseType
Type Inheritance and Interface Implementation
[accessModifier] classDerivedTypeName [: BaseType[, InterfaceTypes...]]
{
// Members
}
Classes can combine inheritance with interfaces
First identify the base type you inherit from
Add additional interfaces as needed
Separate the types with commas
Generic Types
[accessModifier] typeKeyword TypeName<T>
{
// type members
}
Generics can be applied to structs, classes and interfaces, where
[accessModifier] is either public or internal. If no access modifier is provided, then the default modifier is internal
typeKeyword is either class, struct or interface
TypeName is the programmer-supplied name for the data type
T is a generic placeholder for a type declared in a subtype or an instance of the generic
Create "hooks" inside of our methods to invoke other methods as "observers"
"Publish" a single event to multiple "subscribers"
".NET provides the EventHandler and EventHandler<TEventArgs> delegates to support most event scenarios. Use the EventHandler delegate for all events that do not include event data. Use the EventHandler<TEventArgs> delegate for events that include data about the event. These delegates have no return type value and take two parameters (an object for the source of the event, and an object for event data)." (MS Docs)
The End
This is party a refresher for those who have taken introductory C# courses
Your introductory course may or may not have placed emphasis on the grammar
Objects might not have been emphasized, but they are central to the C# language and should be understood as both essential and commonplace
Case-Sensitive => UPPER- and lower-case case characters are different
Type-Safe => The data type of a thing is known at compile-time
Object-Oriented => Object paradigm to provide Polymorphism and Encapsulation
Extensible => You can add to (*extend*) the words built into the language
Keywords
=> Define Data Types (int, string, bool)
=> Provide Points of Extensibility (class, enum, interface)
=> Segment and Link code (namespace, using)
=> Enhance code security and accessibility (public, private, protected, internal)
Identifiers => Names the PROGRAMMER give to things (classes, variables, methods, etc.)
Symbols
=> Provide structure and context (curly braces, semicolon, parenthesis)
=> Operations (Arithmetic, Logical, Relational)
Most of the grammar rules in C# are quite short, defining the order of **keywords**, **identifiers** and **symbols**. In the following grammars, the use of Square brackets (**`[]`**) indicate an optional part of the syntax for the grammar rule; those square brackets are *not* actual symbols in the final syntax of the grammar
Before a variable can be used, it must be *declared*. Declaring a variable tells the compiler to
* set aside room in memory to store information,
* treat that data as a specific data type, and
* refer to that information by the variable name
When an expression is processed by the computer, a single value is produced. This value can then be used in whatever operation the expressions occurs. For example, the value might be passed into a method as part of a method call, or it might be placed in a variable as part of an assignment statement.
**Namespaces** are used to group classes and other programmer-defined data types into a single named group. The reason for grouping programmer-defined data types into namespaces is to prevent what are called "naming collisions". A naming collision is where two or more classes or other programmer-defined data types are given the same name. In other words, you cannot have two classes named `Circle` in the same namespace. However, if you place those two classes in different namespaces, then that is acceptable because the compiler will then be able to distinguish between the two classes based on the namespace they belong to.
Whenever a class or other data type is placed in a namespace, that namespace becomes part of the ***fully-qualified*** name of the data type. For example, if a class named `Circle` is placed in a namespace called `Geometry.Shapes`, then the fully qualified name of the class is `Geometry.Shapes.Circle`.
Namespaces allow us to isolate our classes and other data types into groups. All of the classes/data types in a given namespace can automatically reference each other. To reference or use data types in other namespaces, we must either use their fully-qualified names or *include* them through the **Using Statement**.
As an object-oriented language, classes play a very prominent part of the code we write in C#. It is within classes, for example, that we place variables (also called *fields*) and methods (which are "*named* sets of instructions"). One of the first things that classes give us developers is a *context* or ***scope*** for the code that we write. Classes are also building blocks, acting as blueprints for new and complex data types that we as programmers can create as we develop richer and more complex computer programs. Classes permeate all the code that we write in C# and are so fundamental that you can't even write a "Hello World" program without them.
`satic` - If present, the field is *shared* among all instances of the class. If absent (which is the common case) then the field is an *instance* member and one is created every time an object based on the class is created.
`_FieldName` By convention, private fields are given an underscore as a prefix to the name.
`constantExpression` Being a constant expression does *not* mean that the field is a constant, only that the initial value stored in the field is a constant and can be known at compile time *before* the program runs.
Explicitly implemented properties are properties where the programmer supplies the getter and setter implementations. The bodies of the getter and setter may reference a field (known as a **backing store**) that holds the actual information. In these cases, the property is working to provide a **controlled access** to the underlying field's data.
In other situations, a property may merely have a getter where the body of the getter *derives* or *calculates* a value to return from some other source, such as a calculation.
Autoimplemented properties are properties where the compiler takes care of the getter and setter implementations and also supplies a hidden field as the **backing store** for the property. The default get implementation is to retrieve the value from the backing store while the default set implementation is to place a value into the backing store.
While the [Method Declaration](#method-declarations) *defines a set of instructions*, those instructions only run when the method is *called* from somewhere. The operating system is responsible to call the `Main()` method, but after that, all method calls are the responsibility of our program. The grammar of a method call is as follows.
- `initializations` is a comma-separated set of variable initializations or assignments; the variables identified here should be ones used in the `conditionalExpression`. This portion is optional
- `conditionalExpression` is an expression whose ultimate data type is a `bool`. The `conditionalExpression` is evaluated at the beginning of the loop.
- `incrementations` is a comma-separated set of modifications to the variable(s) controlling the loop; the variables identified here should be ones used in the `conditionalExpression`. This portion is optional.
- `statementOrStatementBlock` is either a **single** statement or a **single** statement *block* (zero or more statements inside curly braces - `{ }`).
- The `statementOrStatementBlock` will only execute as long as the `contitionalExpression` results in a **`true`** value.
- The loop exits when the `conditionalStatement` results in a **`false`** value.