Skip to content

Commit

Permalink
fix warnings in the fundamentals area
Browse files Browse the repository at this point in the history
  • Loading branch information
BillWagner committed Mar 26, 2021
1 parent 3e53ae8 commit 14d61e9
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 169 deletions.
11 changes: 2 additions & 9 deletions docs/csharp/fundamentals/types/anonymous-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ms.assetid: 59c9d7a4-3b0e-475e-b620-0ab86c088e9b

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](../../language-reference/operators/new-operator.md) operator together with an object initializer. For more information about object initializers, see [Object and Collection Initializers](./object-and-collection-initializers.md).
You create anonymous types by using the [new](../../language-reference/operators/new-operator.md) operator together with an object initializer. For more information about object initializers, see [Object and Collection Initializers](../../programming-guide/classes-and-structs/object-and-collection-initializers.md).

The following example shows an anonymous type that is initialized with two properties named `Amount` and `Message`.

Expand All @@ -33,7 +33,7 @@ Console.WriteLine(v.Amount + v.Message);

[!code-csharp[csRef30Features#81](~/samples/snippets/csharp/VS_Snippets_VBCSharp/csRef30Features/CS/csref30.cs#81)]

Typically, when you use an anonymous type to initialize a variable, you declare the variable as an implicitly typed local variable by using [var](../../language-reference/keywords/var.md). 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](./implicitly-typed-local-variables.md).
Typically, when you use an anonymous type to initialize a variable, you declare the variable as an implicitly typed local variable by using [var](../../language-reference/keywords/var.md). 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](../../programming-guide/classes-and-structs/implicitly-typed-local-variables.md).

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.

Expand All @@ -50,10 +50,3 @@ var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape",
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 <xref:System.Object.Equals%2A> and <xref:System.Object.GetHashCode%2A> 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.

## See also

- [C# Programming Guide](../index.md)
- [Object and Collection Initializers](./object-and-collection-initializers.md)
- [Getting Started with LINQ in C#](../concepts/linq/index.md)
- [LINQ in C#](../../linq/index.md)
42 changes: 18 additions & 24 deletions docs/csharp/fundamentals/types/basic-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,63 +26,57 @@ The information stored in a type can include the following:

- 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](language-reference/builtin-types/integral-numeric-types.md), 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](language-reference/builtin-types/bool.md), the compiler generates an error, as shown in the following example:
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](../../language-reference/builtin-types/integral-numeric-types.md), 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](../../language-reference/builtin-types/bool.md), the compiler generates an error, as shown in the following example:

[!code-csharp[Type Safety](../../samples/snippets/csharp/concepts/basic-types/type-safety.cs)]
[!code-csharp[Type Safety](../../../../samples/snippets/csharp/concepts/basic-types/type-safety.cs)]

> [!NOTE]
> C and C++ developers, notice that in C#, [bool](language-reference/builtin-types/bool.md) is not convertible to [int](language-reference/builtin-types/integral-numeric-types.md).
> C and C++ developers, notice that in C#, [bool](../../language-reference/builtin-types/bool.md) is not convertible to [int](../../language-reference/builtin-types/integral-numeric-types.md).
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.

## Specifying types in variable declarations

When you declare a variable or constant in a program, you must either specify its type or use the [var](language-reference/keywords/var.md) 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:
When you declare a variable or constant in a program, you must either specify its type or use the [var](../../language-reference/keywords/var.md) 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:

[!code-csharp[Variable Declaration](../../samples/snippets/csharp/concepts/basic-types/variable-declaration.cs)]
[!code-csharp[Variable Declaration](../../../../samples/snippets/csharp/concepts/basic-types/variable-declaration.cs)]

The types of method parameters and return values are specified in the method signature. The following signature shows a method that requires an [int](language-reference/builtin-types/integral-numeric-types.md) as an input argument and returns a string:
The types of method parameters and return values are specified in the method signature. The following signature shows a method that requires an [int](../../language-reference/builtin-types/integral-numeric-types.md) as an input argument and returns a string:

[!code-csharp[Method Signature](../../samples/snippets/csharp/concepts/basic-types/method-signature.cs)]
[!code-csharp[Method Signature](../../../../samples/snippets/csharp/concepts/basic-types/method-signature.cs)]

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](language-reference/builtin-types/integral-numeric-types.md) 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 conversion* that 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.
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](../../language-reference/builtin-types/integral-numeric-types.md) 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 conversion* that 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.

For more information, see [Casting and type conversions](programming-guide/types/casting-and-type-conversions.md).
For more information, see [Casting and type conversions](../../programming-guide/types/casting-and-type-conversions.md).

## Built-in types

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 the complete list of the built-in types, see [Built-in types](language-reference/builtin-types/built-in-types.md).
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 the complete list of the built-in types, see [Built-in types](../../language-reference/builtin-types/built-in-types.md).

## Custom types

You use the [struct](language-reference/builtin-types/struct.md), [class](language-reference/keywords/class.md), [record](language-reference/builtin-types/record.md), [interface](language-reference/keywords/interface.md), and [enum](language-reference/builtin-types/enum.md) constructs to create your own custom types. The .NET 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.
You use the [struct](../../language-reference/builtin-types/struct.md), [class](../../language-reference/keywords/class.md), [record](../../language-reference/builtin-types/record.md), [interface](../../language-reference/keywords/interface.md), and [enum](../../language-reference/builtin-types/enum.md) constructs to create your own custom types. The .NET 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.

## Generic types

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, <xref:System.Collections.Generic.List%601> 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:

[!code-csharp[Generic types](../../samples/snippets/csharp/concepts/basic-types/generic-type.cs)]
[!code-csharp[Generic types](../../../../samples/snippets/csharp/concepts/basic-types/generic-type.cs)]

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](language-reference/builtin-types/reference-types.md#the-object-type). 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](programming-guide/generics/index.md).
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](../../language-reference/builtin-types/reference-types.md#the-object-type). 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](generics.md).

## Implicit types, anonymous types, and tuple types

As stated previously, you can implicitly type a local variable (but not class members) by using the [var](language-reference/keywords/var.md) 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](programming-guide/classes-and-structs/implicitly-typed-local-variables.md).
As stated previously, you can implicitly type a local variable (but not class members) by using the [var](../../language-reference/keywords/var.md) 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](../../programming-guide/classes-and-structs/implicitly-typed-local-variables.md).

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](programming-guide/classes-and-structs/anonymous-types.md).
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](anonymous-types.md).

It's common to want to return more than one value from a method. You can create *tuple types* that return multiple values in a single method call. For more information, see [Tuple types](language-reference/builtin-types/value-tuples.md).
It's common to want to return more than one value from a method. You can create *tuple types* that return multiple values in a single method call. For more information, see [Tuple types](../../language-reference/builtin-types/value-tuples.md).

## The Common type system

It is important to understand two fundamental points about the type system in .NET:

- 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 <xref:System.Int32> (C# keyword: `int`), derive ultimately from a single base type, which is <xref:System.Object> (C# keyword: `object`). This unified type hierarchy is called the [Common type system](../standard/common-type-system.md) (CTS). For more information about inheritance in C#, see [Inheritance](programming-guide/classes-and-structs/inheritance.md).
- 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 <xref:System.Int32> (C# keyword: `int`), derive ultimately from a single base type, which is <xref:System.Object> (C# keyword: `object`). This unified type hierarchy is called the [Common type system](../../../standard/common-type-system.md) (CTS). For more information about inheritance in C#, see [Inheritance](../../programming-guide/classes-and-structs/inheritance.md).

- Each type in the CTS is defined as either a *value type* or a *reference type*. This includes all custom types in the .NET class library and also your own user-defined types. Types that you define by using the `struct` or `enum` keyword are value types. For more information about value types, see [Value types](language-reference/builtin-types/value-types.md). Types that you define by using the [class](language-reference/keywords/class.md) keyword are reference types. For more information about reference types, see [Classes](programming-guide/classes-and-structs/classes.md). Reference types and value types have different compile-time rules, and different run-time behavior.

## See also

- [Structure types](language-reference/builtin-types/struct.md)
- [Enumeration types](language-reference/builtin-types/enum.md)
- [Classes](programming-guide/classes-and-structs/classes.md)
- Each type in the CTS is defined as either a *value type* or a *reference type*. This includes all custom types in the .NET class library and also your own user-defined types. Types that you define by using the `struct` or `enum` keyword are value types. For more information about value types, see [Value types](../../language-reference/builtin-types/value-types.md). Types that you define by using the [class](../../language-reference/keywords/class.md) keyword are reference types. For more information about reference types, see [Classes](classes.md). Reference types and value types have different compile-time rules, and different run-time behavior.
Loading

0 comments on commit 14d61e9

Please sign in to comment.