Notes Page
This is a list of concrete examples, notes, and links to resources that
I use for reference that I've compiled together from working on projects,
reading books, and online articles. It's very incomplete, actively worked on,
and it is by no means all-encompassing,
ever finished, or meant to be a full resource for any of the listed topics.
Please contact me if you
find any errors or have comments/suggestions.
SQL Server
Connections
Naming Conventions
- Use singular names rather than plural. Ex.
Departmentinstead ofDepartments - Primary Key: tablename_id. Example:
department_id
- Use singular rather than plural names
- Foreign Keys should be named fk_tablename_id. Ex. In the
usertable, the department ID should be namedfk_department_id - Date fields should have the suffix
_on. Ex.created_on - Fields that record the user should be suffixed with
_by. Ex.modified_by
Data Types
|
|
T-SQL
Opperators
SELECT, WHERE, ORDER BY
SELECT column_name
FROM table_name
WHERE column_name = value
ORDER BY some_column DESC, another_column;
SELECT c.LastName FROM Person.Contact c;Nested Subquery
SELECT DISTINCT o.OrderDate, od.ProductID
FROM Sales.SalesOrderHearder soh
JOIN Sales.SalesOrderDetail sod
ON soh.SalesOrderID = sod.SalesOrderID
WHERE soh.orderDate = (Select MIN(OrderDate) FROM Sales.SalesOrderHeader)
SELECT e.EmployeeID, FirstName, LastName
FROM HumanResources,Employee e
JOIN Person.Contact c
ON e.ContactID = c.ContactID
WHERE e.EmployeeID IN
(SELECT DISTINCT EmployeeID FROM HumanResources.JobCandidate)
Correlated Subqueries
- The outer query obtains a record and passes it into the inner query
- The inner query executes based on the passed value(s)
- The inner query then passes the values from its results back out to the outer query, which uses them to finish its processing
SELECT o1.CustomerID, o1.SalesOrderID, o1.OrderDate
FROM Sales.SalesOrderHeader o1
WHERE o1.OrderDate = (Select MIN(o2.OrderDate)
FROM Sales.SalesOrderHEader o2
WHERE o2.CustomerID = o1.CustomerID)
ORDER BY CustomerID
--Select the name of the customer and the first date they ordered something
SELECT c.LastName
(SELECT MIN(OrderDate)
FROM Sales.SalesORderHeader o
WHERE o.ContactID = c.ContactID)
AS "Order Date"
FROM Person.Contact c
Derived Tables
--Find all the customers that ordered not only a minipump, but also the AWC Logo Cap
SELECT DISTINCT c.FirstName, c.LastName
FROM Person.Contact AS c
JOIN (SELECT ContactID
FROM Sales.SalesOrderHeader AS soh
JOIN Sales.SalesOrderDetail AS sod
ON soh.SalesOrderID = sod.SalesOrderID
JOIN Production.Product AS p
ON sod.ProductID = p.ProductID
WHERE p.Name = 'Minipump') pumps
ON c.ContactID = pumps.ContactID
JOIN (SELECT ContactID
FROM Sales.SalesOrderHeader AS soh
JOIN Sales.SalesOrderDetail AS sod
ON soh.SalesOrderID = sod.SalesOrderID
JOIN Production.Product AS p
ON sod.ProductID = p.ProductID
WHERE p.Name = 'AWC Logo Cap') caps
ON c.ContactID = caps.ContactID
ISNULL
ISNULL(NULL, 5) returns 5
ISNULL(5, 15) returns 5
ISNULL(@MyVar, 0) where @MyVar IS NULL returns 0
ISNULL(@MyVar, 0) where @MyVar = 3 returns 3
ISNULL(@MyVar, 0) where @MyVar = 'Ronnie' returns Ronnie
GROUP BY, AGGREGATES
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;
SELECT SalesOrderID, SUM(OrderQty)
FROM Sales.SalesOrderDetail
WHERE SalesOrderID BETWEEN 43684 AND 43686
GROUP BY SalesOrderID
HAVING SUM(OrderQty) > 5;
DISTINCT, UNION
- All UNIONed queries must have the same number of columns in the SELECT list.
- The column headings are are taken only from the first query.
- The default return option for UNION is DISTINCT. For all rows, use UNION ALL.
SELECT DISTINCT column_name FROM table_name;UNION
SELECT column_name FROM table_name1 UNION SELECT column_name FROM table_name2;UNION ALL
SELECT column_name FROM table_name1 UNION ALL SELECT column_name FROM table_name2;
INSERT
INSERT INTO table_name (column1, column2, column3) VALUES (value1, value2, value3); SELECT NEWID = SCOPE_IDENTITY();Example 2. Inserting values from another table
INSERT INTO table_name (column1, column2, column3) SELECT item1, item2, item3 FROM another_table
UPDATE
UPDATE table_name SET column1=value, column2=value2 WHERE some_column=some_valueExample 2. Update records in one table based on values in another table
UPDATE suppliers SET supplier_name = ( SELECT customers.name FROM customers WHERE customers.customer_id = suppliers.supplier_id ) WHERE EXISTS ( SELECT customers.name FROM customers WHERE customers.customer_id = suppliers.supplier_id );
DELETE
DELETE FROM table_name WHERE some_column=some_value
DELETE FROM Actors FROM Actors a LEFT JOIN Film f ON a.FilmID = f.FilmID WHERE f.FilmID IS NULL;
JOINs
INNER JOIN
SELECT column_name FROM table_name1 INNER JOIN table_name2 ON table_name1.column_name=table_name2.column_name
SELECT * FROM HumanResources.Employee e INNER JOIN HumanResources.Employee m ON e.ManagerID = m.EmployeeID;
SELECT e.EmployeeID, ce.FirstName FROM HumanResources.Employee e INNER JOIN HumanResources.Employee m ON e.ManagerID = m.EmployeeID; INNER JOIN Person.Contact ce ON e.ContactID = ce.ContactID INNER JOIN Person.Contact cm ON m.ContactID = cm.ContactID;Reference a table multiple times
SELECT * FROM Employees AS e INNER JOIN Reference AS r1 ON r1.ID = e.FirstID INNER JOIN Reference AS r2 ON r2.ID = e.SecondID INNER JOIN Reference AS r3 ON r3.ID = e.ThirdID INNER JOIN Reference AS r4 ON r4.ID = e.ForthID
OUTER JOIN (LEFT and RIGHT)
- OUTER JOINs can often speed performance when used instead of other options that might produce the same result.
- The first named table is considered as being on the left.
- The second named table is considered as being on the right.
A LEFT JOIN says to include all records from the LEFT side regardless of whether there is a match on the RIGHT side or not.
SELECT column_name
FROM table_name1
LEFT OUTER JOIN table_name2
ON table_name1.column_name=table_name2.column_name
Right Outer Join
A RIGHT JOIN says to include all records from the RIGHT side regardless of whether there is a match on the LEFT side or not.
SELECT column_name
FROM table_name1
RIGHT OUTER JOIN table_name2
ON table_name1.column_name=table_name2.column_name
FULL JOIN
SELECT *
FROM Film f
FULL JOIN Actors a
ON f.FilmID = a.FilmId;
CROSS JOIN
SELECT *
FROM Film f
CROSS JOIN Actors a;
Cast and Convert
CASTis ANSI compliant, andCONVERTisn'tCONVERTalso does some date formatting conversions thatCASTdoesn't
SELECT 'The customer has an order numbered ' + CAST(SalesOrderID AS varchar)
FROM Sales.SalesOrderHeader
WHERE CustomerID = 5
Stored Procedures (sprocs) and User-Defined Functions (UDF)
- Can return a value of most SQL Server types, excluding text, ntext, image, cursor, and timestamp.
- All variables passed into the function are passed by value.
- Recursion and nesting: 32 deep.
Creating, Altering Tables, Keys, and Constraints
CREATE TABLE Customers
{
CustomerNo int IDENTITY NOT NULL PRIMARY KEY,
CustomerName varchar(30) NOT NULL
}
Creating a primary key on an existing table
USE Accounting
ALTER TABLE Employees
ADD CONSTRAINT PK_EmployeeID
PRIMARY KEY (EmployeeID)
Creating Foreign Keys on new tables
USE Accounting
CREATE TABLE Orders
{
OrderID int IDENTITY NOT NULL PRIMARY KEY,
CustomerNo int NOT NULL
FOREIGN KEY REFERENCES Customers(CustomerNo)
}
Adding a Foreign key to an existing table
ALTER TABLE Orders
ADD CONSTRAINT FK_EmployeeCreatesOrder
FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID)
Cascading Actions
CREATE TABLE OrderDetails
{
OrderID int NOT NULL,
PartNo varchar(10),
CONSTRAINT PKOrderDetails
PRIMARY KEY (OrderID, PartNo),
CONSTRAINT FKOrderContainsDetails
FOREIGN KEY (OrderID)
REFERENCES Orders(OrderID)
ON UPDATE NO ACTION
ON DELETE CASCADE
}
Unique Constraints UNIQUE doesn't automatically prevent you from having a NULL value. If you do allow NULLs, you will only be able to insert one of them. Although a NULL doesn't equal another NULL,
they are considered to be duplicate from the perspective of a UNIQUE constraint.
CREATE TABLE Shippers
{
ShipperID int NOT NULL,
ShipperName varchar(10),
UNIQUE
}
ALTER TABLE Employees
{
ADD CONSTRAINT AK_EmployeeSSN
UNIQUE (SSN)
}
Default Constraint
- Defaults are used ony
INSERTstatements; they are ignored forUPDATEandDELETEstatements. - If any value is supplied in the
INSERT, the default isn't used. - If no value is supplied, the default will always be used.
CREATE TABLE Shippers
{
ShipperID int NOT NULL,
ShipperName varchar(10),
DateInSystem smalldatetime NOT NULL
DEFAULT GETDATE ()
}
ALTER TABLE Customers
{
ADD CONSTRAINT CN_CustomerDefaultDateInSYstem
DEFAULT GETDATE() FOR DateInSystem
}
TODO: Rules, Defaults (not DEFAULT)
Indexes
- Clustered Index: Only one clustered index per table is allowed. If an index is clustered, it means that the table on which the clustered index is based is physically sorted according to that index. Think of the page numbers in an encyclopedia.
- Non-clustered Index: Can have many non-clustered indexes per table. Think of the keyword index at the back of the book.
Views
- Views that reference multiple tables generally perform much faster with an indexed view because the join between the tables is preconstructed.
- Aggregations performed in the view are precalculated and stored as part of the index. This means that the aggregation is performed one time (when the row is inserted or updated), and then can be read directly from the index information.
- Inserts and deletes have higher overhead because the index on the view has to be updated immediately; updates also have higher overhead if the key column of the index is affected by the update
Scripts and Batches
Transactions and Locks
Triggers
Full-Text Search
System Databases
- The master database: Critical to the database system and cannot be deleted since it keeps track of the system as a whole. Almost everything that describes your server is in the master database.
- The model database: The model database on which future databases are based. Forms a template for any new database that you create.
- The msdb database: Where SQL Agent process stores any system tasks such as scheduled backups.
- The tempdb database: One of the key working areas for the server. When interim tables are built, they are built in this database. User created temporary tables are created here.
C#
Misc.
- C# 1.0 is statically typed—the compiler knows what members to let you use
- C# 1.0 is explicit—you have to tell the compiler what types variables have
- C# 1.0 is safe—you can’t treat one type as if it were another without the availability of a genuine conversion.
Operators
+, -, !, ~, ++x, --x,(T)x, true, false, &, sizeof
Multiplicative
*, %
Additive
+,-
Shift
<<, >>
Relational and type testing
<,>,<=,>=,is,as
Equality
==, !=
Logical AND
&
int i = 0;
if (false & ++i == 1)
{
// i is incremented, but the conditional
// expression evaluates to false, so
// this block does not execute.
}
Logical XOR^
Logical OR
|
Conditional AND
&&
The conditional-AND operator performs a logical-AND of its bool operands, but only evaluates its second operand if necessary.
Conditional OR
||The conditional-OR operator (||) performs a logical-OR of its bool operands, but only evaluates its second operand if necessary.
Conditional
?:
Assignment
=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, ??
Frameworks
Charting/Graphics
1. Microsoft Chart Controls
Compression/Zip
1. SharpZipLib
2. DotNetZip
Pdf Creators/Generators
1. PDFsharp
2. iTextSharp
Url Rewriting
1. url rewriter
2. UrlRewriting.Net
Dependency Injection
1. Unity Framework - Microsoft
2. StructureMap
3. Castle Windsor
4. NInject
5. Spring Framework
Logging
1. Logging Application Block - Microsoft
2. Log4Net - Apache
3. Error Logging Modules and Handlers(ELMAH)
4. NLog
Ajax
1. Ajax Control Toolkit - Microsoft
ORM
1. NHibernate
Unit Testing/Mocking
1. NUnit
2. Rhino Mocks
3. Moq
4. TypeMock.Net
5. xUnit.net
Automated Web Testing
1. Selenium
Misc
1. CSLA Framework - Business Objects Framework
2. AForge.net
3. Enterprise Library 4.1 - Logging, Exception Management, Validation, Policy Injection
4. File helpers library
5. Recaptcha
Escape Sequences
\' Single quotation mark\" Double quotation mark\\ Backslash\0 Null\a Alert\b Backspace\f Form feed\n Newline\r Carriage return\t Tab character\v Vertical tabstring s = @"C:\Program Files\"; The @ prefixed to a string literal treats the string at face value (even line breaks);
Loops
break can be used to exit from loops. Control will switch to the statement immediately after the end of the loop.
For loop
for (int i=0;i<100;i++) {
//code
}
While loop
while (i<j) {
//code
}
Do while loop
do {
//code
} while (i<j);
foreach loop
foreach (int temp in arrayOfInts) {
//code
}
Enumerations
public enum TimeOfDay {
Morning = 0,
Afternoon = 1,
Evening = 2
}
Obtain an enum value from a string: TimeOfDay time2 = (TimeOfDay) Enum.Parse(typeof(TimeOfDay), "afternoon", true);Console.WriteLine((int)time2);
Arrays
- If the elements of the array are value types, all values are copied when using
clone(). Ex:int[] intArray2 = (int[])intArray1.Clone(); - If the array contains reference types, only the references are copied, not the elements when calling the
clone()method - A shallow clone copies the references but not the referenced objects. A deep clone copies the referenced objects as well. Shallow clones point to the same object when cloning reference types. Deep clones copy the referenced type as well.
- If you need a deep copy of an array containing reference types, you have to iterate the array and create new objects.
Array.Copy()andClone()creates shallow copies.- A shallow comparison is where the objects point to the same point in memory, whereas deep comparisons are working with values and properties of the object to deem equality.
int[] myArray = new int[32]; //creates a new array of 32 ints.
string[] str = new string[]{"a","b","c"};
foreach (string s in str)
Console.WriteLine(s);
Multi Dimension Arrays
int[,] numbers = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };
for (int row = 0; row < numbers.GetLength(0); row++) {
for (int column = 0; column < numbers.GetLength(1); column++) {
Console.Write(numbers[row, column]);
Console.Write(" ");
}
Console.WriteLine("");
}
Jagged Arrays
int[][] numbers = new int[][] { new int[] { 1, 3, 5 }, new int[] { 2, 4, 6, 8, 10 } };
for (int row = 0; row < numbers.Length; row++) {
for (int column = 0; column < numbers[row].Length; column++){
Console.Write(numbers[row][column]);
Console.Write(" ");
}
Console.WriteLine("");
}
Sorting
Array.Sort(someArray)
Properties
public int MyProperty { get; set; }
Prior to C# 3.5
private int _myItem;
public int MyItem
{
get {
return myItem;
}
set {
myItem = value;
}
}
Read Only
private int _myItem;
public int MyItem {
get {
return myItem;
}
}
Namespaces
- Microsoft recommends for most purposes you supply at least two nested namespaces names: the first one
represents teh anme of your company, and the second one represent sthe name of the technology or software
package of which the class is a member. Ex:
YourCompanyName.SalesServices.Customerfor the Customer class. - Namespace Aliases:
using alias = YourCompanyName.SalesServices.Customer;
namespace YourCompanyName.SalesServices {
class Customer {
//code
}
}
XML Code Documentation
Nullable types
//Example 1
decimal? price;
public decimal? Price
{
get { return price; }
private set { price = value; }
}
//Now we can do: Price = null;
//Example 2
int? x = 100;
if (x != null) {...}
The C# ?? null coalescing operator
The ?? operator checks whether the value provided on the left side of the expression is null, and if so it returns an alternate value indicated by the right side of the expression.
string message = "hello world"; string result = message ?? "It was null"; //result == "hello world" string message = null; string result = message ?? "It was null"; //result == "it was null" int? number = null; int result = number ?? 0; //result == 0more info
Preprocessor Directives
Errors and Exceptions
catchis optionalfinallyis optional- The order of the
catchblocks are important - Having to many catch blocks can hurt performance
finallyis executed whether or not an exception is thrown- When writing a library, it is normally best not to handle exceptions (unless you can fixe it), but to instead, assume that the calling code will handle any errors it encounters
- It is perfectly legitimate to throw exceptions from
catchandfinallyblocks
try {
if (index < 0)
throw new IndexOutOfRangeException("Index out of range");
}
catch (OverflowException ex) {
Console.WriteLine(ex.Message);
}
catch {
}
finally {
}
Defining a User-Defined Exception Class
class MyCustomException : ApplicationException {
public MyCustomException(string message)
: base(message)
{
}
public MyCustomException(string message, Exception innerException)
: base(message, innerException)
{
}
}
Throwing and Catching a User-Defined Exception Class
public void SomeMethod() {
//code ...
throw new MyCustomException("something info here");
}
public void SomeOtherMethod() {
try {
}
catch(MyCustomException ex) {
}
}
Destructors, Idisposable, and using
Destructors in C# are really known as finalizers in the underlying .NET architecture. When a destructor is defined,
what is emitted into the assembly by the compiler is actually a method called Finalize(). The problem with C# destructors
as compared to their C++ counterparts is that they are nondeterministic, there is no way to know when an object's destructor
will execute.
Also, C# destructors delay the final removal of an object from memory. Objects without a destructors are removed from memory with one pass of the garbage collector. Objects with a destructor require two: The first pass calls the destructor without removing the object, the second pass deletes the object.
class MyClass {
~MyClass() {
//Code...
}
}
IDisposable
The recommended alternative to using a destructor is using the System.IDisposable interface.
class MyClass : IDisposable {
public void Dispose() {
//Code...
}
}
using
To dispose of an object, call the Dispose() method. The Dispose() call must be in
the finally part of a try/catch or else you run the risk
of failing to free the resources consumed by the object if an exception occurs. This is tedious, so use the using
keyword.
using (ResourceUser obj = new ResourceUser()) {
//use the object
}
This causes the variable to be scoped and when that variable goes out of scope,
it's Dispose() method will be called automatically, even if an exception occurs.
Best practice
The best way to ensure that the
Dispose() method is called is to use both a destructor and impliment
IDisposable.
//not thread safe
using System;
class ResourceHolder : IDisposable {
private bool isDisposed = false;
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (!isDisposed) {
if (disposing) {
//Cleanup managed objects by calling their Dispose() methods
}
//Cleanup unmanaged objects
}
isDisposed = true;
}
~ResourceHolder() {
Dispose (false);
}
public void SomeMethod() {
if(isDisposed) {
throw new ObjectDisposedException("This is disposed");
}
//Code...
}
}
Object and collection initializers (C# 3.0)
Person tom = new Person
{
Name = "Tom",
Age = 4,
Home = { Town="Reading", Country="UK" },
Friends =
{
new Person { Name = "Phoebe" },
new Person("Abi"),
new Person { Name = "Ethan", Age = 4 },
new Person("Ben")
{
Age = 4,
Home = { Town = "Purley", Country="UK" }
}
}
};
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
List<Person> friends = new List<Person>();
public List<Person> Friends { get { return friends; } }
Location home = new Location();
public Location Home { get { return home; } }
public Person() { }
public Person(string name)
{
Name = name;
}
}
public class Location
{
public string Country { get; set; }
public string Town { get; set; }
}
Unsafe Code, pointers
&means "take the address of", and converts a value data type to a pointer. Ex. convertsintto*int*means "get the contents of this address", and converts a pointer to a value data type. Ex. converts*floattofloat- Can declare a pointer to any value type. Not possible to declare a pointer to a class or an array.
- Pointers to structs can't contain any reference types
unsafe class Myclass {
unsafe int* pX;
unsafe int DoSomething() {
//Code...
}
}
class MyClass2 {
void MyMethod() {
unsafe {
int x = 9;
int* pX, pY;
pX = &x;
pY = pX;
*pY = 75;
//so x = 75
Console.WriteLine("Address is " + (uint)pX);
void* pointerToVoid;
pointerToVoid = (void*)pX;
int x = sizeof(double); //sets x to 8
MyStruct Struct = new MyStruct();
pStruct = &Struct;
(*pStruct).X = 4;
//or you can do
pStruct->4;
//high performance arrays
double* pDoubles = stackalloc double[20];
*pDoubles = 3.0;
*(pDoubles+1) = 8.4;
pDoubles[2] = 4.5;
}
}
}
Static
Static Field (Member variables)
class MyClass {
public static int x;
public static int y = 1;
}
Static Member FunctionsA static member function can only access other static members.
class MyClass {
private static int x = 1;
private static int y = 2;
public static void Method() {
Console.WriteLine("{0},{1}",x,y);
}
}
class MyOtherClass {
public static void Main() {
MyClass.Method();
}
}
Static Constructors
public class UserPreferences {
public static readonly int width;
static UserPreferences() {
width = 150;
}
private UserPreferences() {
}
}
//call the class...
int w = UserPreferences.width;
Static Class
static class Utilities {
public static void HelperMethod() { /* Code */ }
}
Struct
- A struct is a value type (not reference type).
- Stored on the heap
- Do not support inheritance
struct Rectangle {
public double Length;
public double Width;
}
struct Rectangle {
public double Length;
public double Width;
Rectangle(double length, double width) {
Length=length;
Width=width;
}
public double Diagonal {
get {
return Math.Sqrt(Length*Length + Width*Width);
}
}
}
foreach (KeyValuePair<int, string> kvp in myStringDict) {
Console.WriteLine("key " + kvp.Key);
Console.WriteLine("Value " + kvp.Value);
}
Interfaces
Interfaces implemented by collections
| Interface | Methods and Properties | Description |
IEnumerable |
GetEnumerator() |
Required if a foreach statement is used with the collection. |
ICollection |
Count, IsSynchronized, SynRoot, CopyTo() |
Implemented by collection classes. Extends IEnumerable |
ICollection<T> |
Count, IsReadOnly, Add(), Clear(), Contains(), CopyTo(), Remove() |
Generic version of ICollection |
IList |
IsFixedSize, IsReadOnly, Item, Add(), Clear(), Contains(), IndexOf(), Insert(), Remove(), RemoveAt() |
Allows you to access a collection using an indexer. Possible to insert or remove elements at any position. |
IList<T> |
Item, IndexOf(), Insert(), RemoveAt() |
|
IDictionary |
IsFixedSize, IsReadOnly, Item, Keys, Values, Add(), Clear(), Contains(), GetEnumerator(), Remove() |
Elements have a key and a value |
IDictionary<TKey,TValue> |
Item, Keys, Values, Add(), ConatinsKey(), Remove(), TryGetValue() |
|
ILookup<TKey,TElement> |
Count, Item, Contains() |
A new interface with .NET 3.5 that is used by collections that have multiple values for a key. The indexer returns an enumeration for a specified key. |
IComparer<T> |
Compare() |
Used to sort elements inside a collection |
IEqualityComparer<T> |
Equals(), GetHashCode() |
Implemented by a comparer that can be used for keys in a dictionary. Objects can be compared for equality. |
public interface IDisposable {
void Dispose();
}
class SomeClass : IDisposable {
public void Dispose() {
// code
}
}
Inheritance
- Modifiers: public, protected, internal, private, protected internal
- Use
baseto call a base class version of a function - Both classes and functions can be declared as abstaract
- An Abstract class cannot be instantiated
- If a class is
sealed, this means that you can't inherit from that class. In the case of a method, you can't override that method. - Interfaces can inherit from other interfaces
class MyDerivedClass : MyBaseClass {
// functions and dta members here
}
Declare that a class derives from another class and also from interfaces
class MyDerivedClass : MyBaseClass, IInterface1, Interface2 {
// functions and dta members here
}
Virtual Methods: By declaring a base class function as virtual, you allow the function (or property) to be overridden in any derived classes
class MyBaseClass {
public virtual string VirtualMethod() {
// code
}
}
class MyDerivedClass : MyBaseClass {
public override string VirtualMethod() {
return "This overrides the VirtualMethod() method";
}
}
Abstract Classes and Functions
abstract class MyAbstractBaseClass {
public abstract int CalculateArea(); //abstract method
}
Sealed Classes and Methods
sealed class FinalClass {
//code
}
Adding Constructors with Parameters to a hierarchy
class SomeDerivedClass : SomeBaseClass {
public SomeDerivedClass(int x, int y) : base (z) {
// code
}
}
Interfaces
public interface IDisposable {
void Dispose();
}
class SomeClass : IDisposable {
public void Dispose() {
// code
}
}
Operator Overloading and User-Defined Casts
- C# requires that all operator overloads be decalred as
publicandstatic. - Comaprison operators are required to be overloaded in pairs. If you overload
==, you must overload!=. The same for>and<. And also for>=and<=. All must return abool. - If you overload
==and!=, you must also overloadEquals()andGetHashCode() - Use the
checkedanduncheckedoperator to force the CLR to envorce overflow checking.
struct Vector {
public double x,y,z;
public Vector(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector(Vector rhs) {
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
public static Vector opertaor + (Vector lhs, Vector rhs) {
Vextor result = new Vector(lhs);
result.x += rhs.x;
result.y += rhs.y;
result.z += rhs.z;
return result;
}
public static bool opertaor == (Vector lhs, Vector rhs) {
//code
}
public static bool opertaor != (Vector lhs, Vector rhs) {
return ! (lhs == rhs)
}
}
User-Defined Casts
struct Currency {
public uint Dollars;
public ushort Cents;
public Currency(uint dollars, ushort cents) {
this.Dollars = dollars;
this.Cents = cents;
}
public static implicit opoerator float (Currency value) {
return value.Dollars + (value.Cents/100.0f);
}
public static explicit operator Currency (float value) {
uint dollars = (uint)value;
ushort cents = (ushort)((value-dollars)*100);
return new Currency(dollars, cents);
}
}
Extension Methods
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. The extension method cannot access private members of the type it extends. Just a new syntax of invoking a static method. You can’t use just any method as an extension method—it has to have the following characteristics:
- It has to be in a non-nested, nongeneric static class (and therefore has to be a static method).
- It has to have at least one parameter.
- The first parameter has to be prefixed with the this keyword.
- The first parameter can’t have any other modifiers (such as out or ref).
- The type of the first parameter must not be a pointer type.
public static class StringExtension {
public static void Foo(this string s) {
Console.WriteLine("Foo invoked");
}
}
//now possible to use Foo() with the string type
string s = "Hello";
s.Foo();
Delegates
- A predicate is a way of testing whether a value matches a criterion.
- An action performs an action with the specified value.
public delegate bool Predicate<T> (T obj)
public delegate void Action<T> (T obj)
Example 1: An extended example
class BubbleSorter {
static public void Sort(object[] sortArray, Comparison comparison) {
for (int i=0;i<sortArray.Length;i++) {
for (int j=i+1;j<sortArray.Length;j++) {
if (comparison(sortArray[j], sortArray[i])) {
object temp = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = temp;
}
}
}
}
}
class Employee {
private string name;
private decimal salary;
public Employee(string name, decimal salary) {
this.name = name;
this.salary = salary;
}
public static bool compareSalary(object x, object y) {
Employee e1 = (Employee) x;
Employee e2 = (Employee) y;
return (e1.salary < e2.salary);
}
}
//use it
class Program {
static void Main() {
Employee[] employees = {
new Employee("B",20),
new Employee("A",10)
};
BubbleSorter.Sort(employees, Employee.CompareSalary);
foreach (var employee in employees)
Console.WriteLine(employee);
}
}
Multicast Delegates
- The order in which methods chained to the same delegate will be called is formally undefined.
- When If one of the methods invoked by a a delegate throws an exception, the complete iteration stops. To avoid this, iterate the list on your own.
delegate void DoubleOp(double value); DoubleOp operations = MathOperations.SomeOtherFunction; operations += MathOperations.SomeOtherFunction;
DemoDelegate d1 = one;
d1 += Two;
Delegate[] delegates = d1.GetInvocationList();
foreach (DemoDelegate d in delegates) {
try {
d();
}
catch (Exception) {
//error
}
}
Anonymous Methods
//C# 2.0
List<Product> products = Product.GetSampleProducts();
products.Sort(delegate(Product first, Product second)
{ return first.Name.CompareTo(second.Name); }
);
//C# 3.0
List<Product> products = Product.GetSampleProducts();
products.Sort(
(first, second) => first.Name.CompareTo(second.Name)
);
//define the delegate somewhere
delegate string DelegateTest(string val);
static void Main() {
string mid = ", middle part,";
DelegateTest anonDel = delegate(string param) {
param += mid;
param += " and this was added to the string.";
return param;
};
Console.WriteLine(anonDel("start of string"));
}
Lambda Expressions
//define the delegate somewhere
delegate string DelegateTest(string val);
static void Main() {
string mid = ", middle part,";
DelegateTest anonDel = param => {
param += mid;
param += " and this was added to the string.";
return param;
};
Console.WriteLine(anonDel("start of string"));
}
Threading
Asynchronous Delegates
//using System.Threading;
public delegate int TakesAWhileDelegate(int data, int ms);
static void Main(string[] args) {
TakesAWhileDelegate d1 = TakesAWhile;
IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null);
while (!ar.IsCompleted) {
// do something in the main thread
Console.Write(".");
Thread.Sleep(50);
}
int result = d1.EndInvoke(ar);
Console.WriteLine("result: {0}", result);
}
static int TakesAWhile(int data, int ms) {
Console.WriteLine("TakesAWhile started");
Thread.Sleep(ms);
Console.WriteLine("TakesAWhile completed");
return ++data;
}
Asynchronous Delegates with Wait Handle
//using System.Threading;
public delegate int TakesAWhileDelegate(int data, int ms);
static void Main(string[] args) {
TakesAWhileDelegate d1 = TakesAWhile;
IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null);
while (true) {
// do something in the main thread
Console.Write(".");
if (ar.AsyncWaitHandle.WaitOne(50, false)) {
Console.WriteLine("Done");
break;
}
}
int result = d1.EndInvoke(ar);
Console.WriteLine("result: {0}", result);
}
static int TakesAWhile(int data, int ms) {
Console.WriteLine("TakesAWhile started");
Thread.Sleep(ms);
Console.WriteLine("TakesAWhile completed");
return ++data;
}
Asynchronous Delegates with Wait Handle
//using System.Threading;
public delegate int TakesAWhileDelegate(int data, int ms);
static void Main(string[] args) {
TakesAWhileDelegate d1 = TakesAWhile;
d1.BeginInvoke(1, 3000, TakesAWhileCompleted, d1);
for (int i = 0; i < 100; i++){
Console.Write(".");
Thread.Sleep(50);
}
}
static int TakesAWhile(int data, int ms) {
Console.WriteLine("TakesAWhile started");
Thread.Sleep(ms);
Console.WriteLine("TakesAWhile completed");
return ++data;
}
static void TakesAWhileCompleted(IAsyncResult ar) {
if (ar==null)
throw new ArgumentNullException("ar");
TakesAWhileDelegate d1 = ar.AsyncState as TakesAWhileDelegate;
int result = d1.EndInvoke(ar);
Console.WriteLine("result: {0}", result);
}
Threading
- The
Threadclass by default is a foreground thread. Set it to background by settingIsBackground - The process of the application keeps running as long as at least one foreground thread is running.
using System;
using System.Threading;
class Program {
static void Main(string[] args) {
Thread t1 = new Thread(ThreadMain);
t1.Name = "TestThread";
t1.Start();
Console.WriteLine("This is the main thred.");
}
static void ThreadMain() {
Console.WriteLine("Thread: {0}", Thread.CurrentThread.Name);
}
}
Figure 2. Passing data to threads through the constructor
using System;
using System.Threading;
public struct Data {
public string Message;
}
class Program {
static void Main(string[] args) {
Data d = new Data();
d.Message = "I want to pass this to the thread";
Thread t1 = new Thread(ThreadMain);
t1.Name = "TestThread";
t1.Start(d);
Console.Read();
}
static void ThreadMain(object o) {
Data d = (Data)o;
Console.WriteLine("Message: {0}", d.Message);
}
}
Figure 3. Passing data to threads by creating a custom class
using System;
using System.Threading;
public class MyThread {
private string data;
public MyThread(string data) {
this.data = data;
}
public void ThreadMain() {
Console.WriteLine(data);
}
}
class Program {
static void Main(string[] args) {
MyThread mt = new MyThread("This is my Thread");
Thread t = new Thread(mt.ThreadMain);
t.Start();
}
}
Synchronization
lock,Interlocked, andMonitorcan be used for synchronization within a process- The classes
Mutex,Event,Semaphore, andReaderWriterLockSlimalso offer synchronization between threads of multiple processes.
- Only one thread can be inside the lock block for the state object.
- Only reference types can be used for a lock.
- The C# compiler resolves the
lockstatement to use theMonitorclass. Monitoras an advantage compared to thelockstatement: you can add a timeout value waiting to get the lock.
using System;
using System.Threading;
public class AThreadingApplication {
private object sync = new object();
int state = 0;
public void ThreadSafeMethod() {
lock (sync) {
//only one thread at a time can access this critical area
if (state == 0)
state++;
state = 0;
}
}
}
Monitor
if (Monitor.TryEnter(obj, 1000)) { //wait 1 second
try {
//have a lock
}
finally {
Monitor.Exit(obj);
}
}
else {
//1 second passed, didn't get the lock
}
Mutex
Mutex offers synchronization across multiple processes.
static class Program {
[STAThread]
static void Main() {
bool cratedNew;
Mutex mutex = new Mutex(false, "SingletonWinAppMutex", out createdNew);
if (!createdNew) {
MessageBox.Show("You can only start one instance of this application");
Application.Exit();
return;
}
}
}
Semaphore
Semaphore is similar to a mutex, but the semaphore can be used by multiple threads at once. A semaphore
is a counting mutex, meaning that you can define the number of threads that are allowed to access the resource guarded by the semaphore simultaneously.
using System;
using System.Threading;
using System.Diagnostics;
class Program {
static void Main() {
int threadCount = 6;
int semaphoreCount = 4;
Semaphore semaphore = new Semaphore(semaphoreCount, semaphoreCount);
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread(ThreadMain);
threads[i].Start(semaphore);
}
for (int i = 0; i < threadCount; i++)
threads[i].Join();
Console.WriteLine("All threads finished");
}
static void ThreadMain(object o) {
Semaphore semaphore = o as Semaphore;
Trace.Assert(semaphore != null, "o must be a Semaphore type");
bool isCompleted = false;
while (!isCompleted) {
if (semaphore.WaitOne(600, false)) {
try {
Console.WriteLine("Thread {0} locks the semaphore", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
}
finally {
semaphore.Release();
Console.WriteLine("Thread {0} releases the semaphore", Thread.CurrentThread.ManagedThreadId);
isCompleted = true;
}
}
else {
Console.WriteLine("timeout for thread {0}; wait again", Thread.CurrentThread.ManagedThreadId);
}
}
}
}
Events
You can use events to inform other threads that some data is here, something is completed, and so on.
using System;
using System.Threading;
public struct InputData {
public int X;
public int Y;
public InputData(int x, int y) {
this.X = x;
this.Y = y;
}
}
public class ThreadTask
{
private AutoResetEvent autoEvent;
public int Result { get; private set; }
public ThreadTask(AutoResetEvent ev) {
this.autoEvent = ev;
}
public void DoSomeLongTask(object obj) {
//do stuff
autoEvent.Set();
}
}
class Program {
static void Main() {
int taskCount = 4;
AutoResetEvent[] autoEvents = new AutoResetEvent[taskCount];
ThreadTask[] tasks = new ThreadTask[taskCount];
for (int i = 0; i < taskCount; i++) {
autoEvents[i] = new AutoResetEvent(false);
tasks[i] = new ThreadTask(autoEvents[i]);
ThreadPool.QueueUserWorkItem(tasks[i].DoSomeLongTask, new InputData(1, 2));
}
for (int i = 0; i < taskCount; i++) {
int index = WaitHandle.WaitAny(autoEvents);
if (index == WaitHandle.WaitTimeout) {
//timedout
}
else {
Console.WriteLine("finished task {0}, result: {1}", index, tasks[index].Result);
}
}
}
}
ReaderWriterLockSlim
Allows multiple readers, but just one writer, to a resource. ReaderWriterLockSlim is new to .net 3.0.
The .net 1.0 ReaderWriterLock was replaced and redesigned to prevent
deadlocks and to offer better performance.
BackgroundWorker
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowsFormsApplication1 {
public struct CalcInput {
public int x;
public int y;
public CalcInput(int x, int y) {
this.x = x;
this.y = y;
}
}
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void btnCalculate_Click(object sender, EventArgs e) {
this.btnCalculate.Enabled = false;
this.btnCancel.Enabled = true;
backgroundWorker1.RunWorkerAsync(new CalcInput(2, 3));
}
private void OnDoWork(object sender, DoWorkEventArgs e) {
//In the backgroundWorker1 control, set the
//DoWork event to this
//To enable progress, must enable WorkerReportsProgress to true;
CalcInput input = (CalcInput)e.Argument;
for (int i = 0; i < 10; i++) {
System.Threading.Thread.Sleep(500);
backgroundWorker1.ReportProgress(i*10);
if (backgroundWorker1.CancellationPending) {
e.Cancel = true;
return;
}
}
e.Result = input.x + input.y;
}
private void OnProgressChanged(object sender, ProgressChangedEventArgs e){
//must set the ProgressChange event to this for the backgroundWorker1
this.progressBar1.Value = e.ProgressPercentage;
}
private void OnWorkCompleted(object sender, RunWorkerCompletedEventArgs e) {
//In the backgroundWorker1 control, set the
//RunWorkCompleted event to this
if (e.Cancelled)
this.txtResult.Text = "Cancelled";
else
this.txtResult.Text = e.Result.ToString();
this.btnCalculate.Enabled = true;
this.btnCancel.Enabled = false;
this.progressBar1.Value = 100;
}
private void btnCancel_Click(object sender, EventArgs e) {
//must set the WorkerSupportsCancellation to true
//on backgroundWorker1
backgroundWorker1.CancelAsync();
}
}
}
Events
Strings
- Use
System.Text.StringBuilderto perform repeated modifications on a string IFormattable
StringBuilder
StringBuilder sb = new StringBuilder("This is a string");
sb.AppendFormat(" This is appended to the string");
sb.Replace("i","R");
String.Format
//dates
DateTime d = Convert.ToDateTime("3/17/2009 12:30:45 AM");
String s = "";
s = d.ToString("d");
s = d.ToString("D");
s = d.ToString("U");
s = d.ToString("y");
s = String.Format("{0:ddd}",d);
s = String.Format("{0:MM/dd/yyyy}",d);
//strings
String.Format("first: {0};second: {1}", "apple", "orange"); //"first: apple;second: orange"
String.Format(”{0:(###) ###-####}”, 8001234567); //(800) 123-4567
//numbers
decimal i = 25.00M;
String.Format("{0:C4}", i); //"$25.0000"
String.Format("{0:C2}", i); //"$25.00"
String.Format("{0:C}", i); //"$25.00"
String.Format("{0:C0}", i); //"$25"
String.Format("{0:00000}", 25); //"00025"
//only two decimal places
String.Format("{0:0.00}", 123.4567); //"123.46"
String.Format("{0:0.00}", 123.4); //"123.40"
String.Format("{0:0.00}", 123.0); //"123.00"
//maximum of two decimal places
String.Format("{0:0.##}", 123.4567); //"123.46"
String.Format("{0:0.##}", 123.4); //"123.4"
String.Format("{0:0.##}", 123.0); //"123"
//at least two digits before decimal point
String.Format("{0:00.0}", 123.4567); //"123.5"
String.Format("{0:00.0}", 23.4567); //"23.5"
String.Format("{0:00.0}", 3.4567); //"03.5"
String.Format("{0:00.0}", -3.4567); //"-03.5"
//leading and trailing zeros
String.Format("{0:0.0}", 0.0); //"0.0"
String.Format("{0:0.#}", 0.0); //"0"
String.Format("{0:#.0}", 0.0); //".0"
String.Format("{0:#.#}", 0.0); //""
Formatting Numbers
- Leading Zeros: D, X
- Trailing Zeros: C, E, F, N, P
| Specifier | Type | Format | Example |
| C | Currenty | {0:C} | $4834.50 |
| D | Integer | {0:D} | 4834 |
| E | Scientific notation | {0:E} | 4.834E+003 |
| F | Fixed -point decimal | {0:F} | 4834.50 |
| G | General number | {0:G} | 4834.5 |
| N | locale-specific format | {0:N} | 4 384,50(Europe) |
| P | Percentage | {0:P} | 432,000.00% |
| X | Hexadecimal | {0:X} | ffffcfc6 |
Formatting Dates
| Specifier | Type | Example |
| d | Short Date | 08/06/1970 |
| D | Long Date | 01 June 1990 |
| t | Short Time | 12:30 |
| T | Long Time | 12:30:59 |
| f | Full date and time | 08 June 1970 12:30 |
| F | Full date and time (long) | 08 June 1970 12:30:59 |
| g | Default date and time | 08/06/1970 12:30 |
| G | Default date and time (long) | 08/06/1970 12:30:59 |
| M | Day / Month | 8 June |
| r | RFC1123 date string | Mon, 08 Jun 1970 12:30:59 GMT |
| s | Sortable date/time | 1970-06-08T12:30:59 |
| u | Universal time, local timezone | 1970-06-08 12:30:59Z |
| Y | Month / Year | June 1970 |
| dd | Day | 08 |
| ddd | Short Day Name | Mon |
| dddd | Full Day Name | Monday |
| hh | 2 digit hour | 12 |
| HH | 2 digit hour (24 hour) | 12 |
| mm | 2 digit minute | 30 |
| MM | Month | 06 |
| MMM | Short Month name | Jun |
| MMMM | Month name | June |
| ss | seconds | 59 |
| tt | AM/PM | PM |
| yy | 2 digit year | 70 |
| yyyy | 4 digit year | 1970 |
| : | {0:hh:mm:ss} | 12:30:59 |
| / | {0:dd/MM/yyyy} | 08/06/1970 |
Add specifiers to your classes
Assume you have a Vecotr struct and need to implement a way to format the ToString() in various ways.
struct Vector : IFormattable {
public double x, y, z;
public string ToString(string format, IFormatProvider formatProvider) {
if (format == null)
return ToString();
string formatUpper = format.ToUpper();
switch (formatUpper) {
case "N":
return "|| " + Norm().ToString() + " ||";
case "VE":
return String.Format("( {0:E}, {1:E}, {2:E} )", x, y, z);
case "IJK":
StringBuilder sb = new StringBUilder(x.ToString(0,30);
sb.ApendFormat(" i + ");
sb.ApendFormat(y.ToString());
sb.ApendFormat(" j + ");
sb.ApendFormat(z.ToString());
sb.ApendFormat(" k");
return sb.ToString();
default:
return ToString();
}
}
}
//example:
//Vector v1 = new Vector(1,32,5);
//Console.WriteLine("The VE format is {0,30:VE}",v1);
Regular Expressions
System.Text.RegularExpressions. The .NET regular expression engine is designed to be mostly compatible with Perl 5 regular expressions, but with some added features.
Pattern Matching
A brief list of Regular Expression Language Elements. To escape a meta character, use the \. For example, to find a period, use \.
| Symbol | Meaning |
| ^ | Beginning of input text (first character of the text) |
| $ | End of input Text |
| . | Any single character except the newline character (\n) |
| * | Preceding character may be repeated zero or more times |
| + | Preceding character may be repeated one or more times |
| ? | Preceding character may be repeated zero or one time |
| \s | Any whitespace character |
| \S | Any character that isn't a whitespace |
| \b | Word boundary. Ex. ion\b matches any word ending in ion |
| \B | Any position that isn't a word boundry. Ex. \BX\B matches any X in the middle of a word. |
| [x|y] | A match that contains alternative characters. Ex. [a|b] means one character that can be either a or b. |
| [a-z] | A range. [a-z] indicates any single lowercase letter. [0-9] indicates a digit. |
| () | Groups characters. Ex. (an)+ locates any recurrences of the sequence an. |
| \w | Match any alphanumeric character |
| \W | Match any character that is NOT alphanumeric |
| \d | Match any digit |
| \D | Match any character that isn't a digit |
| [^aeiou] | Match any character that is not one of the characters a,e,i,o, or u |
string Pattern = "some text to match";
string Text = "Lots of text ... and even more text";
MatchCollection Matches = Regex.Matches(Text, Pattern, RegexOptions.IgnoreCase | RegexOptions. ExplicitCapture);
foreach (Match NextMatch in Matches) {
Console.WriteLine(NextMatch.Index);
//NextMatch.Index: returns the index in the input text of where the match was found.
}
//find words begining with "n".
Pattern = @"\bn";
//find words ending with the sequence "ion"
Pattern = @"ion\b";
//beginning with the letter "a" and ending with "ion"
Patter = @"\ba\S*ion\b";
//Extract the protocol, address, and port from a URL
Pattern = @"\b(\S+)://(\S+)(?::(\S+))?\b";
//Match an IP address
Pattern = @"(\d{1,3}\.){3}\d{1,3}";
Generics
null to a generic type.
List<int> list = new List<int>();
list.Add(123);
int i = list[0]; //no unboxing or casting needed
Creating Generic Classes
public class LinkedListNode<T> {
private T value;
public LinkedListNode(T value) {
this.value = value;
}
public T Value {
get { return value; }
}
private LinkedListNode<T> next;
public LinkedListNode<T> Next; {
get {return next; }
internal set { next = value; }
}
// ... more code for linked lists
}
Null valuesIt isn't possible to assign
null to a generic type. Instead, you must use the default keyword. default initializes generic types either to null if it is a reference type or 0 if it is a value type. Example:
public T DoSomething() {
T someThing = default(T);
return someThing;
}
Constraints: force the type to implement a given interface.
One more set of restrictions: the class you specify can’t be a struct, a sealed class
(such as string), or any of the following “special” types:
System.Object, System.Enum, System.ValueType, System.Delegate
public class SomeClass<TGeneric> where TGeneric : ISomeInterface
//where T : struct
//where T : class
//where T : IFoo
//where T : Foo
//where T : new()
//where T1 : T2
class Sample<T> where T : Stream,IEnumerable<string>,IComparable<int>
class Sample<T> where T : class, Stream, new()
class Sample<T> where T : struct, IDisposable
class Sample<T,U> where T : class where U : struct, T
class Sample<T,U> where T : Stream where U : IDisposable
//Invalid Examples
class Sample<T> where T : class, struct
class Sample<T> where T : Stream, class
class Sample<T> where T : new(), Stream
class Sample<T,U> where T : struct where U : class, T
class Sample<T,U> where T : Stream, U : IDisposable
Inheritance
public class Base<T> {
}
public class Derived<T> : Base<T>
//or: public class Derived<T> : Base<string>
public abstract class Calc<T> {
public abstract T Add(T x, Ty);
public abstract T Sub(T x, Ty);
}
public class SimpleCalc : Calc<int> {
public override int Add(int x, int y) {
return x + y;
}
public override int Sub(int x, int y) {
return x - y;
}
}
Generic Interfaces
public interface IComparable<T> {
int CompareTo(T other);
}
Generic Methods
void Swap<T>(ref T x, ref T y) {
T temp;
temp = x;
x = y;
y = temp;
}
void test() {
int i=8;
int j=9;
Swamp<int>(ref i, ref j);
//Because the C# compiler can get the type of the parameters
//by calling the Swap method, it is not
//required to assign the generic type with the method calld.
Swap(ref i, ref j);
}
Nullable<T>
Nullable<int> x;
x=4;
if (x.HasValue) {
//...
}
x = null;
Collections
Querying collections
//C# 3.0
List<Product> products = Product.GetSampleProducts();
foreach (Product product in products.Where(p => p.Price > 10)) {
Console.WriteLine(product);
}
Lists
List<int> candidates = new List<int>();
for (int i=2; i <= 100; i++) {
candidates.Add(i);
}
//public delegate bool Predicate<T> (T obj)
for (int factor=2; factor <= 10; factor++) {
candidates.RemoveAll (
delegate(int x) {return x>factor && x%factor==0;}
);
}
//public delegate void Action<T> (T obj)
candidates.ForEach (delegate(int prime)
{ Console.WriteLine(prime); }
);
Example 2.
[Serializable]
public class Racer : IComparable<Racer>, IFormattable {
public Racer() : this (String.Empty, String.Empty, String.Empty) {}
public Racer (String firstName, string lastName, string country)
: this(firstName, lastName, country, 0) {}
public Racer(string firstName, string lastName, string country, int wins) {
this.FirstName = firstName;
this.LastName = lastName;
this.Country = country;
this.Wins = wins;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public string Country { get; set; }
public int Wins { get; set; }
public override string ToString() {
return String.Format("{0} {1}", FirstName, LastName);
}
public string ToString (string format, IFormatProvider formatProvider) {
switch (format.ToUpper()) {
case null:
case "N": //name
return ToString();
case "F":
return FirstName;
default:
throw new FormatException(String.Format(formatProvider, "Format not supported",format));
}
}
public string ToString(string format) {
return ToString(format, null);
}
public int CompareTo(Racer other) {
int compare = this.LastName.CompareTo(other.LastName);
if (compare == 0)
return this.FirstName.CompareTo(other.FirstName);
return compare;
}
}
//Now use this class in a List
{
List<Racer> racers = new List<Racer>();
Racer r1 = racers[0];
}
Queues
A queue is a collection where elements are processed firt in, first out (FIFO). You cannot access the queue using an indexer.
Queue<int> q = new Queue<int>();
q.Enqueue(3);
int i = q.Dequeue();
Stacks
A stack is a collection where the item that is added last to the stack is read first (LIFO).
Stack<int> s = new Stack<int>();
s.Push(3);
int i = s.Pop();
Linked Lists
A doubly linked list, where one element references the next and the previous one. The advantage of a linked list is that if items are inserted in the middle of a list, the linked list is very fast. Items of linked lists can be accessed only one after the other. It takes a long time to find an item that's somewhere in the middle or at th end of the list.
LinkedList<int> numbers = new LinkedList<int>();
numbers.AddFirst(1);
numbers.AddFirst(2);
numbers.AddBefore(numbers.Find(2), 3);
numbers.AddAfter(numbers.Find(1), 4);
foreach (int i in numbers) {
//...
}
Sorted Lists
A sorted list that sorts elements based on a key. The important part of SortedList is that when you enumerate it, the entries come out sorted by key.
SortedList<string, string> books = new SortedList<string, string>();
books.Add("C# 3.5", "932-324-234324");
books["C# 3.4"] = "983-345-234234";
foreach (KeyValuePair<string, string> book in books) {
Console.WriteLine("{0}, {1}", book.Key, book.Value);
}
foreach (string isbn in books.Values) {
Console.WriteLine(isbn);
}
foreach (string title in books.Keys) {
//...
}
Dictionaries
Dictionaries allow you to access elements based on a key. They are also known as hash tables or maps. Fast lookup using the key. Can add/remove elements without the performance overhead of having to shift subsequent items in memory. Supports only one value per key.
Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("cat", 1);
d.Add("dog", 4);
d.Add("cow", 6);
d.Add("rooster", -3);
if (d.ContainsKey("dog")) {
int i = d["dog"];
}
if (d.TryGetValue("cow", out value)) {
d["cow"] = value + 1;
}
Lookup
C# 3.5. System.Linq Maps keys to a collections of values.
List<Package> packages = new List<Package> { new Package { Company = "Coho Vineyard", Weight = 25.2, TrackingNumber = 89453312L },
new Package { Company = "Lucerne Publishing", Weight = 18.7, TrackingNumber = 89112755L },
new Package { Company = "Wingtip Toys", Weight = 6.0, TrackingNumber = 299456122L },
new Package { Company = "Contoso Pharmaceuticals", Weight = 9.3, TrackingNumber = 670053128L },
new Package { Company = "Wide World Importers", Weight = 33.8, TrackingNumber = 4665518773L } };
// Create a Lookup to organize the packages. Use the first character of Company as the key value.
// Select Company appended to TrackingNumber for each element value in the Lookup.
Lookup<char, string> lookup = (Lookup<char, string>)packages.ToLookup(p => Convert.ToChar(p.Company.Substring(0, 1)),
p => p.Company + " " + p.TrackingNumber);
// Iterate through each IGrouping in the Lookup and output the contents.
foreach (IGrouping<char, string> packageGroup in lookup) {
// Print the key value of the IGrouping.
Console.WriteLine(packageGroup.Key);
// Iterate through each value in the IGrouping and print its value.
foreach (string str in packageGroup)
Console.WriteLine(" {0}", str);
}
// This code produces the following output:
// C
// Coho Vineyard 89453312
// Contoso Pharmaceuticals 670053128
// L
// Lucerne Publishing 89112755
// W
// Wingtip Toys 299456122
// Wide World Importers 4665518773
// Get the number of key-collection pairs in the Lookup.
int count = lookup.Count;
// Select a collection of Packages by indexing directly into the Lookup.
IEnumerable<string> cgroup = lookup['C'];
Console.WriteLine("\nPackages that have a key of 'C':");
foreach (string str in cgroup)
Console.WriteLine(str);
// This code produces the following output:
// Packages that have a key of 'C'
// Coho Vineyard 89453312
// Contoso Pharmaceuticals 670053128
// Determine if there is a key with the value 'G' in the Lookup.
bool hasG = lookup.Contains('G');
HashSet
An unordered list of distinct items. Inserting items is fast. Can create a union or intersections of sets.
HashSet<string> hs1 = new HashSet<string>() { "a", "b", "c" };
HashSet<string> hs2 = new HashSet<string>() { "b", "c", "d" };
HashSet<string> hs3 = new HashSet<string>(hs1);
hs3.UnionWith(hs2);
if (hs1.Add("e"))
Console.WriteLine("e added");
if (hs1.IsSubsetOf(hs2)) {
//...
}
if (hs1.IsSupersetOf(hs2)) {
//...
}
if (hs1.Overlaps(hs2)) {
//...
}
hs3.ExceptWith(hs2);
Bit Arrays
BitArray, BitVector32.BitarrayUsed to deal with a number of bits. BitArray is resizeable.
BitVector32 is stack-based and therefore faster
Security, Encryption
- MD5
- MD5Cng
- SHA1
- SHA1Managed
- SHA1Cng
- SHA256
- SHA256Managed
- SHA256Cng
- SHA384
- SHA384Managed
- SHA384Cng
- SHA512
- SHA512Managed
- SHA512Cng
- DES
- DESCryptoServiceProvider
- TripleDES
- TripleDESCryptoServiceProvider
- Aes
- AesCryptoServiceProvider
- AesManaged
- RC2
- RC2CryptoServiceProvider
- Rijandel
- RijandelManaged
- DSA
- DSACryptoServiceProvider
- ECDsa
- ECDsaCng
- ECDiffieHellman
- ECDiffieHellmanCng
- RSA
- RSACryptoServideProvider
ADO.net
ADO.net namespaces and misc. notes
- Be wary of any nondatabase-related code that executes while the connection is open.
- It's best to open connections late and close them as early as possible
DataAdapterobject's Fill and Update methods can open and close a connection automatically- Avoid passing an open connection between methods where possible
- To retrieve a single value,
ExecuteReaderandFillmethods are usually overkill. It's More efficient to use theExecuteScalarmethod. - Moving queries to a stored procedure can offer greater performance since the execution plan will be stored in the procedure cache
System.Data: All generic data access classesSystem.Data.Common: Classes shared (or overridden) by individual data providersSystem.Data.Odbc: ODBC provider classesSystem.Data.OleDb: OLE DB provider classSystem.Data.ProviderBase: Base classes and connection factory classesSystem.Data.Oracle: Oracle provider classesSystem.Data.Sql: Generic interfaces and classes for SQL server data accessSystem.Data.SqlClient: SQL Server provider classesSystem.Data.SqlTypes: SQL Server data types
Connection Strings
Server=(local);Database=SomeDatabase;Integrated Security=True;
SQL Express 2005
Server=localhost\SQLEXPRESS;Database=SomeDatabase;Integrated Security=True;
More connections strings can be found at: connectionstrings.com
Executing Queries: Create, open, and close a connection to a database
<configuration>
<configSections/>
<appSettings/>
<connectionStrings>
<add name="MyDatabase" providerName="System.Data.SqlClient" connectionString="Server=localhost\SQLEXPRESS;Database=SomeDatabase;Integrated Security=True;"/>
</connectionStrings>
</configuration>
ExecuteNonQuery
private int ExecuteNonQuery() {
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["MyDatabase"];
string sql = "UPDATE users SET username=@username WHERE user_id=@user_id";
int rowsAffected = 0;
using (SqlConnection conn = new SqlConnection(settings.ConnectionString)) {
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.Add("username", SqlDbType.NVarChar, 20).Value = "New Username";
cmd.Parameters.Add("user_id", SqlDbType.Int).Value = 5;
conn.Open();
rowsAffected = cmd.ExecuteNonQuery();
}
}
return rowsAffected;
}
ExecuteScalar
private string ExecuteScalar() {
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["MyDatabase"];
string sql = "SELECT username FROM users WHERE user_id=@user_id";
string username = "";
using (SqlConnection conn = new SqlConnection(settings.ConnectionString)) {
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.Add("user_id", SqlDbType.Int).Value = 5;
conn.Open();
username = (string)cmd.ExecuteScalar();
}
}
return username;
}
ExecuteReader
private void ExecuteReader() {
//bad idea to return datareaders since it keeps the connection opened
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["MyDatabase"];
string sql = "SELECT * FROM users WHERE user_id>=@user_id";
using (SqlConnection conn = new SqlConnection(settings.ConnectionString)) {
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.Add("user_id", SqlDbType.Int).Value = 0;
conn.Open();
//using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection | CommandBehavior.SingleRow | ...))
using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) {
while (dr.Read())
Response.Write(dr["username"]);
}
}
}
}
Use a DataAdapter
private DataSet ExecuteSqlDataAdapter() {
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["MyDatabase"];
string sql = "SELECT * FROM users WHERE user_id>=@user_id";
DataSet ds = new DataSet();
using (SqlConnection conn = new SqlConnection(settings.ConnectionString)) {
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.Add("user_id", SqlDbType.Int).Value = 0;
SqlDataAdapter da = new SqlDataAdapter(cmd);
conn.Open();
da.Fill(ds, "Users");
}
}
return ds;
}
Calling Stored Procedures
private void ExecuteStoredProcedure() {
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["MyDatabase"];
string sql = "sp_UpdateUser";
using (SqlConnection conn = new SqlConnection(settings.ConnectionString)) {
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
conn.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@UserID", 1));
cmd.Parameters.Add(new SqlParameter("@Username", "abc123"));
cmd.ExecuteNonQuery();
}
}
}
Calling a stored procedure that uses a DataReader
private void ExecuteStoredProcedure() {
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["MyDatabase"];
string sql = "sp_GetUsers";
using (SqlConnection conn = new SqlConnection(settings.ConnectionString)) {
using (SqlCommand cmd = new SqlCommand(sql, conn)) {
conn.Open();
cmd.CommandType = CommandType.StoredProcedure;
using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) {
while (dr.Read())
Response.Write(dr["username"]);
}
}
}
}
Taking Advantage of Output Parameters
In Figure 1 the DataSet would contain the data and all of the supporting metadata as overhead. The stored procedure in Figure 2 can be called from ADO.NET using a Command object. Its values can be retrieved using the Command object's parameter collection. The prGet_Customer (Figure 2) stored procedure is more efficient since it does not need to pass a rowset nor does the client code have to bear the weight of the extra overhead that comes with the DataSet. The three values can be stored in variables requiring less than 100 bytes. In contrast, if you return the same three values into a DataSet from a DataAdapter using the first stored procedure, the DataSet and its schema will be almost 1,000 bytes in size. If all you need are a handful of values from a single row, using the ExecuteScalar or output parameters executes faster than retrieving a rowset into a DataSet, and then having to pass that data to another application tier.
Figure 1 (bad way)
CREATE PROCEDURE prGet_CustomerRowSet
@sCustomerID NCHAR(5)
AS
SELECT CompanyName, ContactName, City
FROM Customers
WHERE CustomerID = @sCustomerID
GO
Figure 2 (better way)
CREATE PROCEDURE prGet_Customer
@sCustomerID NCHAR(5),
@sCompanyName NVARCHAR(40) OUTPUT,
@sContactName NVARCHAR(30) OUTPUT,
@sCity NVARCHAR(15) OUTPUT
AS
SELECT @sCompanyName = CompanyName,
@sContactName = ContactName,
@sCity = City
FROM Customers
WHERE CustomerID = @sCustomerID
GO
Figure 3. Using the ouput parameters in Figure 2.
private void GetOutputValues() {
string connectionString = "Server=(local);Database=Northwind;Integrated Security=True;";
string sProc = "prGet_Customer";
using (SqlConnection conn = new SqlConnection(connectionString)) {
using (SqlCommand cmd = new SqlCommand(sProc, conn)) {
conn.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@sCustomerID", SqlDbType.NChar, 5);
cmd.Parameters["@sCustomerID"].Value = "abcde";
cmd.Parameters.Add("@sCompanyName", SqlDbType.NVarChar, 40);
cmd.Parameters["@sCompanyName"].Direction = ParameterDirection.Output;
cmd.Parameters.Add("@sContactName", SqlDbType.NVarChar, 30);
cmd.Parameters["@sContactName"].Direction = ParameterDirection.Output;
cmd.Parameters.Add("@sCity", SqlDbType.NVarChar, 15);
cmd.Parameters["@sCity"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
string sCompanyName = cmd.Parameters["@sCompanyName"].Value.ToString();
string sContacName = cmd.Parameters["@sContactName"].Value.ToString();
string sCity = cmd.Parameters["@sCity"].Value.ToString();
}
}
}
Transactions
SqlTransaction oTran = null;
try {
oCn.Open();
oTran = oCn.BeginTransaction();
oCmd1.Transaction = oTran;
oCmd1.ExecuteNonQuery();
oCmd2.Transaction = oTran;
oCmd2.ExecuteNonQuery();
oTran.Commit();
}
catch {
oTran.Rollback();
throw;
}
finally {
oCn.Close();
}
More reading and references
LINQ: Language Integrated Query
When query expressions are defined during runtime, the query does not run. The query runs when the items are iterated (Deferred Query Execution).
Standard Query Operators
Where, OrderByDescending, Select, Where OfType<TResult>,
SelectMany, OrderBy, ThenByDescending, Reverse,
Join, GroupJoin, GroupBy, Any, All, Contains,
Take, Skip, TakeWhile, SkipWhile, Distinct, Union,
Intersect, Except
//Assume we have a Formula1 class
var query = from r in Formula1.GetChampions()
where r.Country == "Brazil"
orderby r.Wins descending
select r;
foreach (Racer r in query) {
//...
}
//more examples
var racers = from r in Formula1.GetChampions()
where r.Wins > 15 &&
(r.Country == "Brazil" || r.Country == "Austria")
select r;
//Filtering with Index: Overload of the Where() method
var racers = Formula1.GetChampions().
Where ((r, index) =>
r.LastName.StartsWith("A") &&
index % 2 != 0;
object[] data = {"one", 2, 3, "four", "five"};
var query = data.OfType<string>();
//Compound from
var ferrariDrivers = from r in
Formula1.GetChampions()
from c in r.Cars
where c == "Ferrari"
orderby r.LastName
select r.FirstName + " " + r.LastName;
//sorting
var racers = from r in Formula1.GetChampions()
where r.Country == "Brazil"
orderby r.Wins descending
select r;
//grouping
var countries = from r in
Formula1.getChampions()
group r by r.Country into g
orderby g.Count() descending, g.Key
where g.Count() >= 2
select new { Country = g.Key, Count = g.Count() };
//grouping with Nested Objects
var countries = from r in
Formula1.getChampions()
group r by r.Country into g
orderby g.Count() descending, g.Key
where g.Count() >= 2
select new {
Country = g.Key,
Count = g.Count(),
Racers = from r1 in g
orderby r1.LastName
select r1.FirstName + " " + r1.LastName
};
//join
var racersAndTeams =
from r in racers
join t in teams on r.year equals t.year
select new {
Year = r.Year,
Racer = r.Name,
Team = t.Name
}
//set operations destinct, union, intersect, except
//Partitioning
//Aggregate Operators
var query = from r in Formula1.GetChampions()
where r.Years.Count() > 3
orderby r.Years.Count() descending
select new {
Name = r.FirstName + " " + r.lastName,
TimesChampion = r.Years.count()
}
//Conversions
List<Racer> racers =
(from r in Formula1.GetChampions()
where r.Starts > 150
orderby r.Stars descending
select r).ToList();
//Generation Operators: range, empty, repeat
//Expression Trees
//
web.config and settings files
In a Windows Forms project, there is a folder called Properties and a file called Settings.settings in that folder. Open the Settings.Settings file by double clicking it. The settings file contains two scopes: Application and User.
Application Scope: Not changed by the user. It is constant in every instance of the application.
User Scope: The setting is not constant throughout each instance. It is reset for each user installation.
//save a value name "DefaultSavePath" Properties.Settings.Default.DefaultSavePath = TextBox1.Text; Properties.Settings.Default.Save(); //use the settings TextBox1.Text = Properties.Settings.Default.DefaultSavePath;
web.config
TODO: flush this out
DateTime, Date, Time
Difference between two times
DateTime startTime = DateTime.Now;
DateTime endTime = DateTime.Now.AddSeconds(1234);
TimeSpan span = endTime.Subtract(startTime);
Console.WriteLine("Seconds different: " + span.Seconds);
Console.WriteLine("Minutes different: " + span.Minutes);
Console.WriteLine("Hours different: " + span.Hours);
Console.WriteLine("Days different: " + span.Days);
Timers
System.Timers.TimerSystem.Threading.TimerSystem.Windows.Forms.TimerSystem.Web.UI.Timer
Send Email
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections > </configSections> <system.net> <mailSettings> <smtp from="example@gmail.com" deliveryMethod="Network"> <network host="smtp.gmail.com" port="587" userName="example@gmail.com" password="password" /> </smtp> </mailSettings> </system.net> </configuration>Send the email in your program
//using System.Net.Mail;
var message = new MailMessage();
message.To.Add(new MailAddress("john@example.com", "Mailer"));
message.Body = "Test email";
message.Subject = "Subject";
var client = new SmtpClient();
client.EnableSsl = true;
client.Send(message);
Files and Directories
File, FileInfo, Directory, and DirectoryInfo:
DirectoryandFilecontain only static methods and are never instantiated.DirectoryInfoandFileInfoimplement roughly the same methods, properties, and constructors asDirectoryandFile, but are stateful and the members are not static. Must instantiate these classes before they are used. More efficient if you are doing multiple operations on the same files/folders.
//using System.IO;
DirectoryInfo dir = new DirectoryInfo(@"C:\Program Files");
FileInfo f = new FileInfo(@"C:\file.txt");
f.CopyTo(@"C:\copy.txt");
File.Copy(@"C:\file.txt", @"C:\copy.txt");
File.Delete(@"C:\file.txt");
textbox1.Text = File.ReadAllText(@"C:\copy.txt");
Select a directory and list files in the directory
//using System.IO;
DirectoryInfo dir = new DirectoryInfo("c:\\");
FileInfo[] files = dir.GetFiles();
foreach (FileInfo f in files) {
MessageBox.Show(f.FullName);
}
Read and Writing text files
StreamReader and StreamWriter
class instead of the FileStream class.
Read text file
//using System.IO;
StreamReader sr = new StreamReader(@"C:\file.txt");
int nextChar = sr.Read(); //read a single character
int nChars = 100;
char[] charArray = new char[nChars];
int nCharsRead = sr.Read(charArray, 0, nChars);
string nextLine = sr.ReadLine(); //read an entire line
string restOfFile = sr.ReadToEnd(); //read remainder of the file/stream
sr.Close();
Write text file
//using System.IO;
StreamWriter sw = new StreamWriter(@"C:\file.txt");
sw.Write("This is a new line");
sw.Write('a');
char[] charArray = new char[100];
sw.Write(charArray);
sw.Close();
//create new text file
FileInfo file = new FileInfo(@"C:\newfile.txt");
StreamWriter sw2 = file.CreateText();
sw2.Close();
Read and Writing binary files
FileStreamis intended for reading and writing binary data in a binary file
//using System.IO;
FileStream fs = new FileStream(@"C:\file.doc", FileMode.Create);
int nextByte = fs.ReadByte();
//read an arry of bytes
int nBytesRead = fs.Read(ByteArray, 0, 8);
byte newByte = 100;
fs.WriteByte(newByte);
//write an array of bytes
fs.Write(ByteArray, 0, nBytes);
fs.Close();
Reading Drive Information
DriveInfoprovides information on system drives
//using System.IO;
//list drives on system
DriveInfo[] driveArray = DriveInfo.GetDrives();
foreach (DriveInfo d in driveArray)
Console.WriteLine(d.Name);
DriveInfo di = new DriveInfo("c");
Console.WriteLine(di.VolumeLabel);
Console.WriteLine(di.TotalFreeSpace);
Console.WriteLine(di.TotalSize);
Console.WriteLine(di.DriveFormat);
OpenFileDialog: Select multiple files and bind to a gridview
System.Windows.Forms.OpenFileDialog FileOpen = new System.Windows.Forms.OpenFileDialog();
FileOpen.Multiselect = true;
if (FileOpen.ShowDialog() == DialogResult.OK) {
string[] filename = FileOpen.FileNames;
for (int i=0; i < filename.Length; i++) {
DataGridViewRow row = new DataGridViewRow();
DataGridViewCell cell;
cell = new DataGridViewTextBoxCell();
cell.Value = filename[i];
row.Cells.Add(cell);
cell = new DataGridViewTextBoxCell();
row.Cells.Add(cell);
gridview.Rows.Add(row);
}
}
FolderBrowserDialog: Select a folder and return the path
FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog();
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) {
MessageBox.Show(folderBrowserDialog1.SelectedPath);
}
Drag and Drop
DataGridView to perform DragAndDrop.
First, for the
DataGridView, enable AllowDrop to true.
Next, implement the
DragEnter event.
private void MyDataGridView_DragEnter(object sender, DragEventArgs e) {
//make sure a file is dropped, nothing else
if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
e.Effect = DragDropEffects.All;
}
Next, implement the DragDrop event of the target control (DataGridView).
private void MyDataGridVie_DragDrop(object sender, DragEventArgs e) {
//get the files names dropped
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
//process files...
}
Windows Registry
CreateSubKeycreates the key if it does not already exist. If it doesn't exist, it will return aRegistryKeyinstance that represents the existing key.
//using Microsoft.Win32;
//read access
RegistryKey hklm = Registry.LocalMachine;
RegistryKey hkSoftware = hklm.OpenSubKey("Software");
RegistryKey hkMicrosoft = hklm.OpenSubKey("Microsoft");
//read/write access
RegistryKey hklm2 = Registry.LocalMachine;
RegistryKey hkSoftware2 = hklm.OpenSubKey("Software",true);
RegistryKey hkNew = hkSoftware2.CreateSubKey("NewKey");
hkNew.SetValue("NewStringValue", "Hello World");
hkNew.SetValue("NewIntValue", 123);
string stringValue = (string)hkNew.GetValue("NewStringValue");
hkNew.Close();
ASP.NET MVC
Action Results
- ViewResult – Represents HTML and markup.
- EmptyResult – Represents no result.
- RedirectResult – Represents a redirection to a new URL.
- JsonResult – Represents a JavaScript Object Notation result that can be used in an AJAX application.
- JavaScriptResult – Represents a JavaScript script.
- ContentResult – Represents a text result.
- FileContentResult – Represents a downloadable file (with the binary content).
- FilePathResult – Represents a downloadable file (with a path).
- FileStreamResult – Represents a downloadable file (with a file stream).
- View – Returns a ViewResult action result.
- Redirect – Returns a RedirectResult action result.
- RedirectToAction – Returns a RedirectToRouteResult action result.
- RedirectToRoute – Returns a RedirectToRouteResult action result.
- Json – Returns a JsonResult action result.
- JavaScriptResult – Returns a JavaScriptResult.
- Content – Returns a ContentResult action result.
- File – Returns a FileContentResult, FilePathResult, or FileStreamResult depending on the parameters passed to the method.
Visual Studio 2008
Misc.
- VS 2008 can target .net 2.0, 3.0, or 3.5
Javascript
== vs === (and !==)
0 == ''; //true
'' == '0'; //false
0 === ''; //false
'' === '0'; //false
0 == '0'; //true
0 === '0';//false
Reserved Words
abstract
boolean break byte
case catch char class const continue
debugger default delete do double
else enum export extends
false final finally float for function
goto
if implements import in instanceof int interface
long
native new null
package private protected public
return
short static super switch synchronized
this throw throws transient true try typeof
var volatile void
while with
Numbers
- JavaScript has a single number type - represented as 64-bit floating point
- 1 and 1.0 are the same value
- The value
NaNis a number value that is the result of an operation that cannot produce a normal result.NaNis not equal to any value, including itself. You can detect NaN with the isNaN( number ) function. - The value Infinity represents all values greater than 1.79769313486231570e+308.
- Math.floor( number ) method can be used to convert a number into an integer
Strings
- All characters in JavaScript are 16 bits wide
- JavaScript does not have a character type. To represent a character, make a string with just one character in it.
- The \u convention allows for specifying character code points numerically.
"A" === "\u0041"
Statements
falsenullundefined- The empty string ''
- The number
0 - The number
NaN
true- the string
'false' - all objects
Objects and Object Literals
- Objects are passed around by reference. They are never copied
A property's name can be any string, including the empty string. The quotes around a property's name in an object literal are optional if the name would be a legal JavaScript name and not a reserved word. So quotes are required around "first-name", but are optional around first_name.
var empty_object = {};
var person = {
"first-name": "John",
"last-name": "Smith"
};
person["first-name"] //John
var flight = {
airline: "Oceanic",
number: 815,
departure: {
IATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: {
IATA: "LAX",
time: "2004-09-23 10:42",
city: "Los Angeles"
}
};
flight.departure.IATA // "SYD"
The undefined value is produced if an attempt is made to retrieve a nonexistent member:stooge["middle-name"] // undefined
If the object does not already have that property name, the object is augmented:
person['middle-name'] = 'Bob';
References
- Professional SQL Server 2005 Programming (Programmer to Programmer, Wrox) by Robert Vieira
- Professional C# 2008 (Wrox) by Christian Nagel, Bill Evjen, Jay Glynn, Morgan Skinner, Karli Watson
- SyntaxHighlighter
- stackoverflow.com
- Jon Skeet's C# and .NET articles and links
