Types (C# Programming Guide)
Visual Studio 2013
7 out of 13 rated
this helpful - Rate this topic
C# is a strongly-typed language. Every variable and constant has a type,
as does every expression that evaluates to a value. Every method signature
specifies a type for each input parameter and for the return value. The .NET
Framework class library defines a set of built-in numeric types as well as more
complex types that represent a wide variety of logical constructs, such as the
file system, network connections, collections and arrays of objects, and dates.
A typical C# program uses types from the class library as well as user-defined
types that model the concepts that are specific to the program's problem
domain.
The information stored in a type can include the following:
- The storage space that a variable of the type requires.
- The maximum and minimum values that it can represent.
- The members (methods, fields, events, and so on) that it contains.
- The base type it inherits from.
- The location where the memory for variables will be allocated at run time.
- The kinds of operations that are permitted.
The compiler uses type information to make sure that all operations that
are performed in your code are type safe. For example, if you
declare a variable of type int, the compiler
allows you to use the variable in addition and subtraction operations. If you
try to perform those same operations on a variable of type bool, the compiler
generates an error, as shown in the following example:
C#
int a = 5;
int b = a + 2; //OK
bool test = true;
// Error. Operator
'+' cannot be applied to operands of type 'int' and 'bool'.
int c = a + test;
Note
|
The compiler embeds the type information into the executable file as
metadata. The common language runtime (CLR) uses that metadata at run time to
further guarantee type safety when it allocates and reclaims memory.
When you declare a variable or constant in a program, you must either
specify its type or use the var keyword to
let the compiler infer the type. The following example shows some variable
declarations that use both built-in numeric types and complex user-defined
types:
C#
// Declaration
only:
float temperature;
string name;
MyClass myClass;
// Declaration with
initializers (four examples):
char firstLetter = 'C';
var limit = 3;
int[] source = { 0, 1,
2, 3, 4, 5 };
var query = from item in source
where item <= limit
select item;
The types of method parameters and return values are specified in the
method signature. The following signature shows a method that requires an int as an input
argument and returns a string:
C#
public string GetName(int ID)
{
if (ID < names.Length)
return names[ID];
else
return String.Empty;
}
private string[] names = { "Spencer", "Sally", "Doug" };
After a variable is declared, it cannot be re-declared with a new type,
and it cannot be assigned a value that is not compatible with its declared
type. For example, you cannot declare an int and then
assign it a Boolean value of true. However, values
can be converted to other types, for example when they are assigned to new
variables or passed as method arguments. A type conversionthat does
not cause data loss is performed automatically by the compiler. A conversion
that might cause data loss requires a cast in the source code.
C# provides a standard set of built-in numeric types to represent
integers, floating point values, Boolean expressions, text characters, decimal
values, and other types of data. There are also built-in string and object types.
These are available for you to use in any C# program. For a more information
about the built-in types, see Reference Tables for Types (C# Reference).
You use the struct, class, interface, and enum constructs to
create your own custom types. The .NET Framework class library itself is a
collection of custom types provided by Microsoft that you can use in your own
applications. By default, the most frequently used types in the class library
are available in any C# program. Others become available only when you
explicitly add a project reference to the assembly in which they are defined.
After the compiler has a reference to the assembly, you can declare variables
(and constants) of the types declared in that assembly in source code. For more
information, see .NET Framework Class Library.
It is important to understand two fundamental points about the type
system in the .NET Framework:
- It supports the principle of inheritance. Types can derive from other types, called base types. The derived type inherits (with some restrictions) the methods, properties, and other members of the base type. The base type can in turn derive from some other type, in which case the derived type inherits the members of both base types in its inheritance hierarchy. All types, including built-in numeric types such as System.Int32 (C# keyword: int), derive ultimately from a single base type, which isSystem.Object (C# keyword: object). This unified type hierarchy is called the Common Type System (CTS). For more information about inheritance in C#, see Inheritance (C# Programming Guide).
- Each type in the CTS is defined as either a value type or a reference type. This includes all custom types in the .NET Framework class library and also your own user-defined types. Types that you define by using the struct keyword are value types; all the built-in numeric types are structs. Types that you define by using the class keyword are reference types. Reference types and value types have different compile-time rules, and different run-time behavior.
The following illustration shows the relationship between value types
and reference types in the CTS.
Value types and reference types in the CTS
Note
|
You can see that the most commonly used types are all organized in
the System namespace.
However, the namespace in which a type is contained has no relation to
whether it is a value type or reference type.
|
Value types derive from System.ValueType, which derives
from System.Object. Types that derive
from System.ValueType have special
behavior in the CLR. Value type variables directly contain their values, which
means that the memory is allocated inline in whatever context the variable is
declared. There is no separate heap allocation or garbage collection overhead
for value-type variables.
The built-in numeric types are structs, and they have properties and
methods that you can access:
C#
// Static method on
type Byte.
byte b = Byte.MaxValue;
But you declare and assign values to them as if they were simple
non-aggregate types:
C#
byte num = 0xA;
int i = 5;
char c = 'Z';
Value types
are sealed, which means, for example, that you cannot derive a type
from System.Int32, and you cannot define a struct to
inherit from any user-defined class or struct because a struct can only inherit
from System.ValueType. However, a struct can implement one
or more interfaces. You can cast a struct type to an interface type; this
causes a boxing operation to wrap the struct inside a
reference type object on the managed heap. Boxing operations occur when you
pass a value type to a method that takes aSystem.Object as an input parameter. For more
information, see Boxing and
Unboxing (C# Programming Guide).
You use the struct keyword to
create your own custom value types. Typically, a struct is used as a container
for a small set of related variables, as shown in the following example:
C#
public struct CoOrds
{
public int x, y;
public CoOrds(int p1, int p2)
{
x = p1;
y = p2;
}
}
For more information about structs, see Structs (C# Programming Guide). For more information about value types in the .NET Framework,
see Common Type System.
The other category of value types is enum. An enum defines a
set of named integral constants. For example, theSystem.IO.FileMode enumeration
in the .NET Framework class library contains a set of named constant integers
that specify how a file should be opened. It is defined as shown in the
following example:
C#
public enum FileMode
{
CreateNew = 1,
Create = 2,
Open = 3,
OpenOrCreate = 4,
Truncate = 5,
Append = 6,
}
The System.IO.FileMode.Create constant has a value of
2. However, the name is much more meaningful for humans reading the source
code, and for that reason it is better to use enumerations instead of constant
literal numbers. For more information, seeSystem.IO.FileMode.
All enums inherit from System.Enum, which inherits
from System.ValueType. All the rules
that apply to structs also apply to enums. For more information about enums,
see Enumeration Types (C# Programming Guide).
A type that is defined as a class, delegate, array, or interface is a reference
type. At run time, when you declare a variable of a reference type, the
variable contains the value null until you
explicitly create an instance of the object by using the new operator, or
assign it an object that has been created elsewhere by using new, as
shown in the following example:
C#
MyClass mc = new MyClass();
MyClass mc2 = mc;
An interface must be initialized together with a class object that
implements it. If MyClass implements IMyInterface, you create an instance of IMyInterface as shown in the following example:
C#
IMyInterface iface = new MyClass();
When the object is created, the memory is allocated on the managed heap,
and the variable holds only a reference to the location of the object. Types on
the managed heap require overhead both when they are allocated and when they
are reclaimed by the automatic memory management functionality of the CLR,
which is known as garbage collection. However, garbage collection
is also highly optimized, and in most scenarios it does not create a
performance issue. For more information about garbage collection, see Automatic Memory Management.
All arrays are reference types, even if their elements are value types.
Arrays implicitly derive from the System.Array class, but
you declare and use them with the simplified syntax that is provided by C#, as
shown in the following example:
C#
// Declare and
initialize an array of integers.
int[] nums = { 1, 2, 3,
4, 5 };
// Access an instance
property of System.Array.
int len = nums.Length;
Reference types fully support inheritance. When you create a class, you
can inherit from any other interface or class that is not defined as sealed, and other classes
can inherit from your class and override your virtual methods. For more
information about how to create your own classes, see Classes and Structs (C# Programming Guide). For more information about inheritance and virtual methods, see Inheritance (C# Programming Guide).
In C#, literal values receive a type from the compiler. You can specify
how a numeric literal should be typed by appending a letter to the end of the
number. For example, to specify that the value 4.56 should be treated as a
float, append an "f" or "F" after the number:4.56f. If no letter is appended, the compiler will infer a type for the
literal. For more information about which types can be specified with letter
suffixes, see the reference pages for individual types in Value Types (C# Reference).
Because literals are typed, and all types derive ultimately from System.Object, you can write and
compile code such as the following:
C#
string s = "The answer is
" + 5.ToString();
// Outputs: "The
answer is 5"
Console.WriteLine(s);
Type type =
12345.GetType();
// Outputs:
"System.Int32"
Console.WriteLine(type);
A type can be declared with one or more type parameters that
serve as a placeholder for the actual type (the concrete type) that
client code will provide when it creates an instance of the type. Such types
are called generic types. For example, the .NET Framework typeSystem.Collections.Generic.List<T> has one type parameter that by convention is given the name T.
When you create an instance of the type, you specify the type of the objects
that the list will contain, for example, string:
C#
List<string> strings = new List<string>();
The use of the type parameter makes it possible to reuse the same class
to hold any type of element, without having to convert each element to object. Generic
collection classes are called strongly-typed collections because
the compiler knows the specific type of the collection's elements and can raise
an error at compile-time if, for example, you try to add an integer to
the strings object in the previous example. For more information, see Generics (C# Programming Guide).
As stated previously, you can implicitly type a local variable (but not
class members) by using the var keyword. The
variable still receives a type at compile time, but the type is provided by the
compiler. For more information, see Implicitly Typed Local Variables (C# Programming
Guide).
In some cases, it is inconvenient to create a named type for simple sets
of related values that you do not intend to store or pass outside method
boundaries. You can create anonymous types for this purpose.
For more information, see Anonymous Types (C# Programming Guide).
Ordinary value types cannot have a value of null. However, you can
create nullable value types by affixing a ? after the type.
For example, int? is an int type that can
also have the value null. In the CTS,
nullable types are instances of the generic struct typeSystem.Nullable<T>. Nullable types are especially useful when you are passing data to and from
databases in which numeric values might be null. For more information,
see Nullable Types (C# Programming Guide)..
Implicitly Typed Local Variables (C# Programming
Guide)
Visual Studio 2013
5 out of 5 rated
this helpful - Rate this topic
Local variables can be given an inferred "type" of var instead
of an explicit type. The var keyword instructs the compiler to
infer the type of the variable from the expression on the right side of the
initialization statement. The inferred type may be a built-in type, an
anonymous type, a user-defined type, or a type defined in the .NET Framework
class library. For more information about how to initialize arrays with var,
see Implicitly Typed Arrays (C# Programming Guide).
The following examples show various ways in which local variables can be
declared with var:
C#
// i is compiled as
an int
var i = 5;
// s is compiled as a
string
var s = "Hello";
// a is compiled as
int[]
var a = new[] { 0, 1, 2 };
// expr is compiled
as IEnumerable<Customer>
// or perhaps
IQueryable<Customer>
var expr =
from c in customers
where c.City == "London"
select c;
// anon is compiled
as an anonymous type
var anon = new { Name = "Terry", Age = 34 };
// list is compiled
as List<int>
var list = new List<int>();
It is important to understand that the var keyword does
not mean "variant" and does not indicate that the variable is loosely
typed, or late-bound. It just means that the compiler determines and assigns
the most appropriate type.
The var keyword may be used in the following contexts:
- On local variables (variables declared at method scope) as shown in the previous example.
- In a for initialization statement.
·
for(var x = 1; x < 10; x++)
- In a foreach initialization statement.
·
foreach(var item in list){...}
- In a using statement.
·
using (var file = new
StreamReader("C:\\myfile.txt")) {...}
For more information, see How to: Use Implicitly Typed Local Variables and
Arrays in a Query Expression (C# Programming Guide).
In many cases the use of var is optional and is just a
syntactic convenience. However, when a variable is initialized with an
anonymous type you must declare the variable as var if you
need to access the properties of the object at a later point. This is a common
scenario in LINQ query expressions. For more information, see Anonymous Types (C# Programming Guide).
From the perspective of your source code, an anonymous type has no name.
Therefore, if a query variable has been initialized withvar, then the
only way to access the properties in the returned sequence of objects is to
use var as the type of the iteration variable in the foreach statement.
C#
class ImplicitlyTypedLocals2
{
static void Main()
{
string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
// If a query produces a sequence of
anonymous types,
// then use var in the foreach
statement to access the properties.
var upperLowerWords =
from w in words
select new { Upper = w.ToUpper(), Lower =
w.ToLower() };
// Execute the query
foreach (var ul in upperLowerWords)
{
Console.WriteLine("Uppercase:
{0}, Lowercase: {1}", ul.Upper, ul.Lower);
}
}
}
/* Outputs:
Uppercase: APPLE, Lowercase: apple
Uppercase: BLUEBERRY, Lowercase: blueberry
Uppercase: CHERRY, Lowercase: cherry
*/
The following restrictions apply to implicitly-typed variable
declarations:
- var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
- var cannot be used on fields at class scope.
- Variables declared by using var cannot be used in the initialization expression. In other words, this expression is legal: int i = (i = 20); but this expression produces a compile-time error: var i = (i = 20);
- Multiple implicitly-typed variables cannot be initialized in the same statement.
- If a type named var is in scope, then the var keyword will resolve to that type name and will not be treated as part of an implicitly typed local variable declaration.
You may find that var can also be useful with query
expressions in which the exact constructed type of the query variable is
difficult to determine. This can occur with grouping and ordering operations.
The var keyword can also be useful when the specific
type of the variable is tedious to type on the keyboard, or is obvious, or does
not add to the readability of the code. One example where var is
helpful in this manner is with nested generic types such as those used with
group operations. In the following query, the type of the query variable
is IEnumerable<IGrouping<string, Student>>. As long as you and others who must maintain your code understand this,
there is no problem with using implicit typing for convenience and brevity.
C#
// Same as previous
example except we use the entire last name as a key.
// Query variable is
an IEnumerable<IGrouping<string, Student>>
var studentQuery3 =
from student in students
group student by student.Last;
However, the use of var does have at least the
potential to make your code more difficult to understand for other developers.
For that reason, the C# documentation generally uses var only
when it is required.
Anonymous Types (C# Programming Guide)
Visual
Studio 2013
Anonymous types provide a convenient way to encapsulate a set of
read-only properties into a single object without having to explicitly define a
type first. The type name is generated by the compiler and is not available at
the source code level. The type of each property is inferred by the compiler.
You create anonymous types by using the new operator
together with an object initializer. For more information about object
initializers, see Object and Collection Initializers
(C# Programming Guide).
The following example shows an anonymous type that is
initialized with two properties named Amount and Message.
C#
var v = new { Amount = 108, Message = "Hello" };
// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount + v.Message);
Anonymous types typically are used in the select clause
of a query expression to return a subset of the properties from each object in
the source sequence. For more information about queries, see LINQ Query Expressions (C#
Programming Guide).
Anonymous types contain one or more public read-only properties.
No other kinds of class members, such as methods or events, are valid. The
expression that is used to initialize a property cannot be null,
an anonymous function, or a pointer type.
The most common scenario is to initialize an anonymous type with
properties from another type. In the following example, assume that a class
exists that is named Product. Class Product includes Color and Price properties,
together with other properties that you are not interested in. Variable products is a
collection of Product objects. The anonymous type
declaration starts with the new keyword.
The declaration initializes a new type that uses only two properties from Product. This causes a smaller amount of data to be returned in the
query.
If you do not specify member names in the anonymous type, the
compiler gives the anonymous type members the same name as the property being
used to initialize them. You must provide a name for a property that is being
initialized with an expression, as shown in the previous example. In the
following example, the names of the properties of the anonymous type are Color and Price.
C#
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
Typically, when you use an anonymous type to initialize a
variable, you declare the variable as an implicitly typed local variable by
usingvar. The type name cannot be specified in the variable declaration
because only the compiler has access to the underlying name of the anonymous
type. For more information about var, see Implicitly Typed Local Variables (C#
Programming Guide).
You can create an array of anonymously typed elements by
combining an implicitly typed local variable and an implicitly typed array, as
shown in the following example.
C#
var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};
Anonymous types are class types
that derive directly from object, and that cannot be cast to any type except object. The compiler provides a name for each anonymous type, although
your application cannot access it. From the perspective of the common language
runtime, an anonymous type is no different from any other reference type.
If two or more anonymous object initializers in an assembly
specify a sequence of properties that are in the same order and that have the
same names and types, the compiler treats the objects as instances of the same
type. They share the same compiler-generated type information.
You cannot declare a field, a property, an event, or the return
type of a method as having an anonymous type. Similarly, you cannot declare a
formal parameter of a method, property, constructor, or indexer as having an
anonymous type. To pass an anonymous type, or a collection that contains
anonymous types, as an argument to a method, you can declare the parameter as
type object. However, doing this defeats the purpose of strong typing. If you
must store query results or pass them outside the method boundary, consider
using an ordinary named struct or class instead of an anonymous type.
Because the Equals and GetHashCode methods
on anonymous types are defined in terms of the Equals and GetHashcode methods
of the properties, two instances of the same anonymous type are equal only if
all their properties are equal.
Object and Collection Initializers (C# Programming Guide)
Visual
Studio 2013
Object initializers let you assign values to any accessible
fields or properties of an object at creation time without having to invoke a
constructor followed by lines of assignment statements. The object initializer
syntax enables you to specify arguments for a constructor or omit the arguments
(and parentheses syntax). The following example shows how to use an object
initializer with a named type, Catand how to invoke the
default constructor. Note the use of auto-implemented properties in the Cat class.
For more information, seeAuto-Implemented Properties (C#
Programming Guide).
C#
class Cat
{
// Auto-implemented properties.
public int Age { get; set; }
public string Name { get; set; }
}
C#
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Although object initializers can be used in any context, they
are especially useful in LINQ query expressions. Query expressions make
frequent use of anonymous types, which can only be initialized by using an object initializer, as
shown in the following declaration.
var pet = new { Age = 10, Name = "Fluffy" };
Anonymous types enable the select clause
in a LINQ query expression to transform objects of the original sequence
into objects whose value and shape may differ from the original. This is useful
if you want to store only a part of the information from each object in a
sequence. In the following example, assume that a product object (p) contains many fields and
methods, and that you are only interested in creating a sequence of objects
that contain the product name and the unit price.
C#
var productInfos =
from p in products
select new { p.ProductName, p.UnitPrice };
When this query is executed, the productInfos variable
will contain a sequence of objects that can be accessed in a foreachstatement
as shown in this example:
foreach(var p in productInfos){...}
Each object in the new anonymous type has two public properties
which receive the same names as the properties or fields in the original
object. You can also rename a field when you are creating an anonymous type;
the following example renames theUnitPrice field
to Price.
select new {p.ProductName, Price = p.UnitPrice};
It is a compile-time error to use an object initializer with a
nullable struct.
Collection initializers let you specify one or more element
initializers when you initialize a collection class that implementsIEnumerable. The element initializers can be a simple value, an expression
or an object initializer. By using a collection initializer you do not have to
specify multiple calls to the Add method of the class in your source
code; the compiler adds the calls.
The following examples shows two simple collection initializers:
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> digits2 = new List<int> { 0 + 1, 12 % 3, MakeInt() };
The following collection initializer uses object initializers to
initialize objects of the Cat class defined in a previous
example. Note that the individual object initializers are enclosed in braces
and separated by commas.
C#
List<Cat> cats = new List<Cat>
{
new Cat(){ Name = "Sylvester", Age=8 },
new Cat(){ Name = "Whiskers", Age=2 },
new Cat(){ Name = "Sasha", Age=14 }
};
You can specify null as an
element in a collection initializer if the collection's Add method allows it.
C#
List<Cat> moreCats = new List<Cat>
{
new Cat(){ Name = "Furrytail", Age=5 },
new Cat(){ Name = "Peaches", Age=4 },
null
};
C#
// The following code consolidates examples from the topic.
class ObjInitializers
{
class Cat
{
// Auto-implemented properties.
public int Age { get; set; }
public string Name { get; set; }
}
static void Main()
{
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
List<Cat> cats = new List<Cat>
{
new Cat(){ Name = "Sylvester", Age=8 },
new Cat(){ Name = "Whiskers", Age=2 },
new Cat(){ Name = "Sasha", Age=14 }
};
List<Cat> moreCats = new List<Cat>
{
new Cat(){ Name = "Furrytail", Age=5 },
new Cat(){ Name = "Peaches", Age=4 },
null
};
// Display results.
System.Console.WriteLine(cat.Name);
foreach (Cat c in cats)
System.Console.WriteLine(c.Name);
foreach (Cat c in moreCats)
if (c != null)
System.Console.WriteLine(c.Name);
else
System.Console.WriteLine("List element has null value.");
}
// Output:
//Fluffy
//Sylvester
//Whiskers
//Sasha
//Furrytail
//Peaches
//List element has null value.
}
For more information, see the following topics:
- Casting and Type Conversions (C# Programming Guide)
- Boxing and Unboxing (C# Programming Guide)
- Using Type dynamic (C# Programming Guide)
- Value Types (C# Reference)
- Reference Types (C# Reference)
- Classes and Structs (C# Programming Guide)
- Anonymous Types (C# Programming Guide)
- Generics (C# Programming Guide)
- Variables and Expressions in Beginning Visual C# 2010
Built-In Types Table (C# Reference)
The following table shows the keywords for built-in C# types, which are
aliases of predefined types in the System namespace.
C# Type
|
.NET Framework Type
|
System.Boolean
|
|
System.Byte
|
|
System.SByte
|
|
System.Char
|
|
System.Decimal
|
|
System.Double
|
|
System.Single
|
|
System.Int32
|
|
System.UInt32
|
|
System.Int64
|
|
System.UInt64
|
|
System.Object
|
|
System.Int16
|
|
System.UInt16
|
|
System.String
|
All of the types in the table, except object and string,
are referred to as simple types.
The C# type keywords and their aliases are interchangeable. For example,
you can declare an integer variable by using either of the following
declarations:
int x = 123;
System.Int32 x = 123;
To display the actual type for any C# type, use the system method GetType(). For example, the following statement displays the system alias that
represents the type of myVariable:
Console.WriteLine(myVariable.GetType());
Value Types (C# Reference)
The value types consist of two main categories:
Structs fall into these categories:
- Numeric types
- bool
- User defined structs.
Variables that are based on value types directly contain values. Assigning
one value type variable to another copies the contained value. This differs
from the assignment of reference type variables, which copies a reference to
the object but not the object itself.
Unlike with reference types, you cannot derive a new type from a value
type. However, like reference types, structs can implement interfaces.
Unlike reference types, a value type cannot contain the null value.
However, the nullable types feature does
allow for value types to be assigned to null.
Each value type has an implicit default constructor that initializes the
default value of that type. For information about default values of value
types, see Default Values Table.
Simple types can be initialized by using literals. For example, 'A' is a
literal of the type char and 2001 is a literal of the
type int.
Local variables in C# must be initialized before they are used. For
example, you might declare a local variable without initialization as in the
following example:
int myInt;
You cannot use it before you initialize it. You can initialize it using
the following statement:
myInt = new
int(); // Invoke default constructor for
int type.
This statement is equivalent to the following statement:
myInt = 0; // Assign an initial value, 0 in this
example.
You can, of course, have the declaration and the initialization in the
same statement as in the following examples:
int myInt = new
int();
–or–
int myInt = 0;
Using the new operator
calls the default constructor of the specific type and assigns the default
value to the variable. In the preceding example, the default constructor
assigned the value 0 to myInt. For more information about values assigned by calling default
constructors, see Default Values Table.
With user-defined types, use new to invoke the
default constructor. For example, the following statement invokes the default
constructor of the Point struct:
Point p = new
Point(); // Invoke default constructor for the struct.
After this call, the struct is considered to be definitely assigned;
that is, all its members are initialized to their default values.
A struct type is a value type that is typically used to
encapsulate small groups of related variables, such as the coordinates of a
rectangle or the characteristics of an item in an inventory. The following
example shows a simple struct declaration:
public struct Book
{
public decimal price;
public string title;
public string author;
}
Structs can also contain constructors, constants, fields, methods, properties, indexers, operators, events, and nested types, although if
several such members are required, you should consider making your type a class
instead.
Structs can implement an interface but they cannot inherit from another
struct. For that reason, struct members cannot be declared asprotected.
The enum keyword is used to declare an enumeration, a
distinct type that consists of a set of named constants called the enumerator
list.
Usually it is best to define an enum directly within a namespace so that
all classes in the namespace can access it with equal convenience. However, an
enum can also be nested within a class or struct.
By default, the first enumerator has the value 0, and the value of each
successive enumerator is increased by 1. For example, in the following
enumeration, Sat is 0, Sun is 1, Mon is 2, and so forth.
enum Days {Sat, Sun,
Mon, Tue, Wed, Thu, Fri};
Enumerators can use initializers to override the default values, as
shown in the following example.
enum Days {Sat=1,
Sun, Mon, Tue, Wed, Thu, Fri};
In this enumeration, the sequence of
elements is forced to start from 1 instead
of 0. However, including a constant that has the value of 0 is recommended.
For more information, see Enumeration Types (C# Programming Guide).
Reference Types (C# Reference)
here are two kinds of types in C#: reference types and value
types. Variables of reference types store references to their data (objects),
while variables of value types directly contain their data. With reference
types, two variables can reference the same object; therefore, operations on
one variable can affect the object referenced by the other variable. With value
types, each variable has its own copy of the data, and it is not possible for
operations on one variable to affect the other (except in the case of ref and
out parameter variables, see ref (C# Reference) and out parameter modifier (C# Reference)).
The following keywords are used to declare reference types:
·
class
·
delegate
C# also provides the following built-in reference types:
·
dynamic
·
object
·
string
*******************************************************************************
C Sharp Var data type and Anonymous Type
Var
data type was introduced in C# 3.0. var is used to declare implicitly typed
local variable means it tells the compiler to figure out the type of the
variable at compilation time. A var variable must be initialized at the time of
declaration.
Valid var statements
1. var str = "1";
2. var num = 0;
3. string s = "string";
4. var s2 = s;
5. s2 = null;
6. string s3 = null;
7. var s4 = s3;
At compile time, the above var statements are compiled to IL, like this:
1. string str = "1";
2. int num = 0;
3. string s2 = s;
4. string s4 = s3;
The compile-time type value of var variable cannot be null but the runtime value can be null.
1. // invalid var statements
2. var v; //need to initialize
3. var num = null; // can’t be null at compile time
Once var variable is initialized its data type became fixed to the type of the initial data.
1. // invalid var statements
2. var v2 = "str12";
3. v2 = 3; // int value can’t be assign to implicitly type string variable v2
Anonymous Types
An anonymous type is a
simple class generated by the compiler on the run time to store a set of
values. var data type and new keyword is used to create an anonymous type.
1. var emp = new { Name = "Deepak", Address = "Noida", Salary=21000 };
At compile time, the compiler will create an anonymous type, as follows:
1. class __Anonymous1
2. {
3. private string name;
4. private string address;
5. int salary; public string Name
6. {
7. get{return name; }
8. set { name=value }
9. }
10. public string Address
11. {
12. get{ return address; }
13. set{ address=value; }
14. }
15. public int Salary
16. {
17. get{ return salary; }
18. set{ salary=value; }
19. }
20.}
The anonymous type is very useful when you want to shape the result in your desired form like this:
1. var result =from book in Books
2. where book.Price > 200
3. orderby book.IssueDate descending
4. select new
5. {
6. Name = book.Name,
7. IssueNumber = "#" + book.Issue
8. };
In
above example, I change the name of the “Issue” field of Book table to
“IssueNumber” and add # before value to get desired output.
Introduction
Anonymous types allow us to create
new type without defining them. This is way to defining read only properties
into a single object without having to define type explicitly. Here Type is
generating by the compiler and it is accessible only for the current block of
code. The type of properties is also inferred by the compiler.
We can create anonymous types by using “new” keyword together with the object initializer.
Example
We can create anonymous types by using “new” keyword together with the object initializer.
Example
var anonymousData = new
{
ForeName = "Jignesh",
SurName = "Trivedi"
};
Console.WriteLine("First Name : " + anonymousData.ForeName);
{
ForeName = "Jignesh",
SurName = "Trivedi"
};
Console.WriteLine("First Name : " + anonymousData.ForeName);
Anonymous Types with LINQ Example
Anonymous types are also used with the "Select" clause of LINQ query expression to return subset of properties.
Example
If Any object collection having properties called FirstName , LastName, DOB etc. and you want only FirstName and LastName after the Querying the data then.
Anonymous types are also used with the "Select" clause of LINQ query expression to return subset of properties.
Example
If Any object collection having properties called FirstName , LastName, DOB etc. and you want only FirstName and LastName after the Querying the data then.
class MyData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
public string MiddleName { get; set; }
}
static void Main(string[] args)
{
// Create Dummy Data to fill Collection.
List<MyData> data = new List<MyData>();
data.Add(new MyData { FirstName = "Jignesh", LastName = "Trivedi", MiddleName = "G", DOB = new DateTime(1990, 12, 30) });
data.Add(new MyData { FirstName = "Tejas", LastName = "Trivedi", MiddleName = "G", DOB = new DateTime(1995, 11, 6) });
data.Add(new MyData { FirstName = "Rakesh", LastName = "Trivedi", MiddleName = "G", DOB = new DateTime(1993, 10, 8) });
data.Add(new MyData { FirstName = "Amit", LastName = "Vyas", MiddleName = "P", DOB = new DateTime(1983, 6, 15) });
data.Add(new MyData { FirstName = "Yash", LastName = "Pandiya", MiddleName = "K", DOB = new DateTime(1988, 7, 20) });
}
var anonymousData = from pl in data
select new { pl.FirstName, pl.LastName };
foreach (var m in anonymousData)
{
Console.WriteLine("Name : " + m.FirstName + " " + m.LastName);
}
}
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
public string MiddleName { get; set; }
}
static void Main(string[] args)
{
// Create Dummy Data to fill Collection.
List<MyData> data = new List<MyData>();
data.Add(new MyData { FirstName = "Jignesh", LastName = "Trivedi", MiddleName = "G", DOB = new DateTime(1990, 12, 30) });
data.Add(new MyData { FirstName = "Tejas", LastName = "Trivedi", MiddleName = "G", DOB = new DateTime(1995, 11, 6) });
data.Add(new MyData { FirstName = "Rakesh", LastName = "Trivedi", MiddleName = "G", DOB = new DateTime(1993, 10, 8) });
data.Add(new MyData { FirstName = "Amit", LastName = "Vyas", MiddleName = "P", DOB = new DateTime(1983, 6, 15) });
data.Add(new MyData { FirstName = "Yash", LastName = "Pandiya", MiddleName = "K", DOB = new DateTime(1988, 7, 20) });
}
var anonymousData = from pl in data
select new { pl.FirstName, pl.LastName };
foreach (var m in anonymousData)
{
Console.WriteLine("Name : " + m.FirstName + " " + m.LastName);
}
}
Anonymous type is class type which is
directly derived from “System.Object” and it cannot be cast any type other than
the object. The Compiler generates a name for each anonymous type. If two or
more anonymous type objects are define in the same assembly and the sequence of
properties are same in terms of names and types than the compiler treats as
same object instances of type. It cannot be declared fields, events, or the
return type of a method which having anonymous type. Same as it cannot be
declared formal parameter of method, property, constructor or indexer which having
anonymous type.
Anonymous type VS Dynamic Type
Anonymous type VS Dynamic Type
- NET framework 4.0 introduced new keyword called "Dynamic". Object of type dynamic bypasses the static type checking at time of compilation whereas for anonymous type, creating static type and checking type at compile time.
- Anonymous type is a class type that contain one or more read only properties whereas dynamic can be any type it may be any type integer, string, object or class.
- Anonymous types are assigned type by the compiler.
- Anonymous type is directly derived from System.Object whereas Dynamic is differ from object type and DLR (dynamic Language Runtime) define and assign type runtime.
- Anonymous types throw compile time errors, Dynamic types does not throw any compile time error but throw run-time errors.
- For Anonymous type, Visual studio able to show intellisense because type is known at the time compilation whereas intellisense is not available with dynamic because type is defines at runtime.
Dynamic Type example
dynamic dynamicData = 5;
Console.WriteLine("Data of dynamic type : " + dynamicData);
dynamicData = "Jignesh Trivedi";
Console.WriteLine("Data of dynamic type : " + dynamicData);
Console.WriteLine("Data of dynamic type : " + dynamicData);
dynamicData = "Jignesh Trivedi";
Console.WriteLine("Data of dynamic type : " + dynamicData);
Summary
- Anonymous types are class type, directly derived from “System.Object” so they are reference type.
- If two or more Anonymous types have the same properties in same order in a same assembly then compiler treats it as same type.
- All properties of anonymous type are read only.
- **************
Quick facts about Anonymous type
·
Anonymous types are reference types
derived form system.objects.
·
Properties of the Anonymous type are
read only.
·
If two Anonymous types have the same
properties and same order, then the compiler treats it as the same type, but if
both are in one assembly.
·
Anonymous type has method scope. If
you want to return Anonymous type from the method, then you have to convert it
in object type. But is not good practice.
http://www.dotnet-tricks.com/Tutorial/csharp/40ID180612-C-Sharp-Anonymous-Method.html
C Sharp Anonymous Method
namespace anonymus_Delegate
{
public delegate void My(string a);
delegate void NumberChanger(int n);
class TestDelegate
{
static
int num = 10;
public void ShowNUM(int p)
{
Console.WriteLine("ShowNUM Method: {0}", p);
}
public
static void
AddNum(int p)
{
num += p;
Console.WriteLine("Named Method: {0}", num);
}
public
static void
MultNum(int q)
{
num *= q;
Console.WriteLine("Named Method: {0}", num);
}
public
static int
getNum()
{
return
num;
}
static
void Main(string[]
args)
{
//create
delegate instances using anonymous method
NumberChanger
nc = delegate(int
x)
{
Console.WriteLine("Anonymous Method: {0}", x);
};
//calling
the delegate using the anonymous method
nc(10);
//instantiating
the delegate using the named methods
nc = new
NumberChanger(AddNum);
//calling
the delegate using the named methods
nc(5);
//instantiating
the delegate using another named methods
nc = new
NumberChanger(MultNum);
//calling
the delegate using the named methods
nc(2);
My
m = delegate(string
s) { Console.WriteLine(s); };
m("amit");
TestDelegate
t = new TestDelegate();
nc = new
NumberChanger(t.ShowNUM);
nc(9);
Console.ReadKey();
}
}
}
The concept of anonymous method was introduced in C# 2.0. An anonymous
method is inline unnamed method in the code. It is created using the delegate
keyword and doesn’t required name and return type. Hence we can say, an
anonymous method has only body without name, optional parameters and return
type. An anonymous method behaves like a regular method and allows us to write
inline code in place of explicitly named methods.
Features of anonymous method
- A variable, declared outside the anonymous method can be accessed inside the anonymous method.
- A variable, declared inside the anonymous method can’t be accessed outside the anonymous method.
- We use anonymous method in event handling.
- An anonymous method, declared without parenthesis can be assigned to a delegate with any signature.
- Unsafe code can’t be accessed within an anonymous method.
- An anonymous method can’t access the ref or out parameters of an outer scope.
Assign an Anonymous Method to a
Delegate
1.
2. delegate int MathOp(int a, int b);
3. static void Main()
4. {
5. //statements
6. MathOp op = delegate(int a, int b) { return a + b; };
7. int result = op(13, 14);
8. //statements
9. }
10.
Anonymous Method as an Event Handler
1. <form id="form1" runat="server">
2. <div align="center">
3. <h2>Anonymous Method
Example</h2>
4. <br />
5. <asp:Label ID="lblmsg" runat="server" ForeColor="Green" Font-Bold="true"></asp:Label>
6. <br /><br />
7. <asp:Button ID="btnSubmit" runat="server" Text="Submit" />
8. <asp:Button ID="btnCancel" runat="server" Text="Cancel" />
9. </div>
10. </form>
1. protected void Page_Load(object sender, EventArgs e)
2. {
3. // Click Event handler using Regular
method
4. btnCancel.Click += new EventHandler(ClickEvent);
5. // Click Event handler using
Anonymous method
6. btnSubmit.Click += delegate { lblmsg.Text="Submit Button
clicked using Anonymous method"; };
7. }
8. protected void ClickEvent(object sender, EventArgs e)
9. {
10. lblmsg.Text="Cancel Button
clicked using Regular method";
11. }
Object and Collection Initializers (C# Programming Guide)
Object initializers let you assign values to any accessible fields or properties of an object at creation time without having to invoke a constructor followed by lines of assignment statements. The object initializer syntax enables you to specify arguments for a constructor or omit the arguments (and parentheses syntax). The following example shows how to use an object initializer with a named type, Cat and how to invoke the default constructor. Note the use of auto-implemented properties in the Cat class. For more information, see Auto-Implemented Properties (C# Programming Guide).
class Cat { // Auto-implemented properties. public int Age { get; set; } public string Name { get; set; } }
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Although object initializers can be used in any context, they are especially useful in LINQ query expressions. Query expressions make frequent use ofanonymous types, which can only be initialized by using an object initializer, as shown in the following declaration.
var pet = new { Age = 10, Name = "Fluffy" };
Anonymous types enable the select clause in a LINQ query expression to transform objects of the original sequence into objects whose value and shape may differ from the original. This is useful if you want to store only a part of the information from each object in a sequence. In the following example, assume that a product object (p) contains many fields and methods, and that you are only interested in creating a sequence of objects that contain the product name and the unit price.
var productInfos = from p in products select new { p.ProductName, p.UnitPrice };
When this query is executed, the productInfos variable will contain a sequence of objects that can be accessed in a foreach statement as shown in this example:
foreach(var p in productInfos){...}
Each object in the new anonymous type has two public properties which receive the same names as the properties or fields in the original object. You can also rename a field when you are creating an anonymous type; the following example renames the UnitPrice field to Price.
select new {p.ProductName, Price = p.UnitPrice};
Collection initializers let you specify one or more element initializers when you initialize a collection class that implements IEnumerable. The element initializers can be a simple value, an expression or an object initializer. By using a collection initializer you do not have to specify multiple calls to the Add method of the class in your source code; the compiler adds the calls.
The following examples shows two simple collection initializers:
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; List<int> digits2 = new List<int> { 0 + 1, 12 % 3, MakeInt() };
The following collection initializer uses object initializers to initialize objects of the Cat class defined in a previous example. Note that the individual object initializers are enclosed in braces and separated by commas.
List<Cat> cats = new List<Cat> { new Cat(){ Name = "Sylvester", Age=8 }, new Cat(){ Name = "Whiskers", Age=2 }, new Cat(){ Name = "Sasha", Age=14 } };
You can specify null as an element in a collection initializer if the collection's Add method allows it.
List<Cat> moreCats = new List<Cat> { new Cat(){ Name = "Furrytail", Age=5 }, new Cat(){ Name = "Peaches", Age=4 }, null };
// The following code consolidates examples from the topic. class ObjInitializers { class Cat { // Auto-implemented properties. public int Age { get; set; } public string Name { get; set; } } static void Main() { Cat cat = new Cat { Age = 10, Name = "Fluffy" }; List<Cat> cats = new List<Cat> { new Cat(){ Name = "Sylvester", Age=8 }, new Cat(){ Name = "Whiskers", Age=2 }, new Cat(){ Name = "Sasha", Age=14 } }; List<Cat> moreCats = new List<Cat> { new Cat(){ Name = "Furrytail", Age=5 }, new Cat(){ Name = "Peaches", Age=4 }, null }; // Display results. System.Console.WriteLine(cat.Name); foreach (Cat c in cats) System.Console.WriteLine(c.Name); foreach (Cat c in moreCats) if (c != null) System.Console.WriteLine(c.Name); else System.Console.WriteLine("List element has null value."); } // Output: //Fluffy //Sylvester //Whiskers //Sasha //Furrytail //Peaches //List element has null value. }
********
****************************************************************************
https://www.youtube.com/watch?v=SsvJY33vc5g
No comments:
Post a Comment