You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/csharp/fundamentals/object-oriented/index.md
+8-8
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
2
title: "Classes, structs, and records"
3
3
description: Describes the use of classes, structures (structs), and records in C#.
4
-
ms.date: 03/23/2022
4
+
ms.date: 04/11/2025
5
5
helpviewer_keywords:
6
6
- "structs [C#], about structs"
7
7
- "records [C#], about records"
@@ -14,17 +14,17 @@ helpviewer_keywords:
14
14
---
15
15
# Overview of object oriented techniques in C\#
16
16
17
-
In C#, the definition of a type—a class, struct, or record—is like a blueprint that specifies what the type can do. An object is basically a block of memory that has been allocated and configured according to the blueprint. This article provides an overview of these blueprints and their features. The [next article in this series](objects.md) introduces objects.
17
+
In C#, the definition of a type—a class, struct, or record—is like a blueprint that specifies what the type can do. An object is basically a block of memory allocated and configured according to the blueprint. This article provides an overview of these blueprints and their features. The [next article in this series](objects.md) introduces objects.
18
18
19
19
## Encapsulation
20
20
21
-
*Encapsulation* is sometimes referred to as the first pillar or principle of object-oriented programming. A class or struct can specify how accessible each of its members is to code outside of the class or struct. Methods and variables that aren't intended to be used from outside of the class or assembly can be hidden to limit the potential for coding errors or malicious exploits. For more information, see the [Object-oriented programming](../tutorials/oop.md) tutorial.
21
+
*Encapsulation* is sometimes referred to as the first pillar or principle of object-oriented programming. A class or struct can specify how accessible each of its members is to code outside of the class or struct. Member not intended for consumers outside of the class or assembly are hidden to limit the potential for coding errors or malicious exploits. For more information, see the [Object-oriented programming](../tutorials/oop.md) tutorial.
22
22
23
23
## Members
24
24
25
25
The *members* of a type include all methods, fields, constants, properties, and events. In C#, there are no global variables or methods as there are in some other languages. Even a program's entry point, the `Main` method, must be declared within a class or struct (implicitly when you use [top-level statements](../program-structure/top-level-statements.md)).
26
26
27
-
The following list includes all the various kinds of members that may be declared in a class, struct, or record.
27
+
The following list includes all the various kinds of members that can be declared in a class, struct, or record.
28
28
29
29
- Fields
30
30
- Constants
@@ -56,7 +56,7 @@ The default accessibility is `private`.
56
56
57
57
Classes (but not structs) support the concept of inheritance. A class that derives from another class, called the *base class*, automatically contains all the public, protected, and internal members of the base class except its constructors and finalizers.
58
58
59
-
Classes may be declared as [abstract](../../language-reference/keywords/abstract.md), which means that one or more of their methods have no implementation. Although abstract classes cannot be instantiated directly, they can serve as base classes for other classes that provide the missing implementation. Classes can also be declared as [sealed](../../language-reference/keywords/sealed.md) to prevent other classes from inheriting from them.
59
+
Classes can be declared as [abstract](../../language-reference/keywords/abstract.md), which means that one or more of their methods have no implementation. Although abstract classes can't be instantiated directly, they can serve as base classes for other classes that provide the missing implementation. Classes can also be declared as [sealed](../../language-reference/keywords/sealed.md) to prevent other classes from inheriting from them.
60
60
61
61
For more information, see [Inheritance](./inheritance.md) and [Polymorphism](./polymorphism.md).
62
62
@@ -66,7 +66,7 @@ Classes, structs, and records can implement multiple interfaces. To implement fr
66
66
67
67
## Generic Types
68
68
69
-
Classes, structs, and records can be defined with one or more type parameters. Client code supplies the type when it creates an instance of the type. For example, the <xref:System.Collections.Generic.List%601> class in the <xref:System.Collections.Generic> namespace is defined with one type parameter. Client code creates an instance of a `List<string>` or `List<int>` to specify the type that the list will hold. For more information, see [Generics](../types/generics.md).
69
+
Classes, structs, and records can be defined with one or more type parameters. Client code supplies the type when it creates an instance of the type. For example, the <xref:System.Collections.Generic.List%601> class in the <xref:System.Collections.Generic> namespace is defined with one type parameter. Client code creates an instance of a `List<string>` or `List<int>` to specify the type that the list holds. For more information, see [Generics](../types/generics.md).
70
70
71
71
## Static Types
72
72
@@ -86,9 +86,9 @@ You can instantiate and initialize class or struct objects, and collections of o
86
86
87
87
## Anonymous Types
88
88
89
-
In situations where it isn't convenient or necessary to create a named class you use anonymous types. Anonymous types are defined by their named data members. For more information, see [Anonymous types](../types/anonymous-types.md).
89
+
In situations where it isn't convenient or necessary to create a named class you use anonymous types. Named data members define anonymous types. For more information, see [Anonymous types](../types/anonymous-types.md).
90
90
91
-
## Extension Methods
91
+
## Extension Members
92
92
93
93
You can "extend" a class without creating a derived class by creating a separate type. That type contains methods that can be called as if they belonged to the original type. For more information, see [Extension methods](../../programming-guide/classes-and-structs/extension-methods.md).
Copy file name to clipboardExpand all lines: docs/csharp/linq/how-to-extend-linq.md
+12-55
Original file line number
Diff line number
Diff line change
@@ -2,11 +2,11 @@
2
2
title: "How to: Write your own extensions to LINQ"
3
3
description: Learn techniques to extend the standard LINQ methods. Query based on runtime state, modify query objects, and extend LINQ capabilities.
4
4
ms.topic: how-to
5
-
ms.date: 04/22/2024
5
+
ms.date: 04/11/2025
6
6
---
7
7
# How to extend LINQ
8
8
9
-
All LINQ based methods follow one of two similar patterns. They take an enumerable sequence. They return either a different sequence, or a single value. The consistency of the shape enables you to extend LINQ by writing methods with a similar shape. In fact, the .NET libraries have gained new methods in many .NET releases since LINQ was first introduced. In this article, you see examples of extending LINQ by writing your own methods that follow the same pattern.
9
+
All LINQ based methods follow one of two similar patterns. They take an enumerable sequence. They return either a different sequence, or a single value. The consistency of the shape enables you to extend LINQ by writing methods with a similar shape. In fact, the .NET libraries gained new methods in many .NET releases since LINQ was first introduced. In this article, you see examples of extending LINQ by writing your own methods that follow the same pattern.
10
10
11
11
## Add custom methods for LINQ queries
12
12
@@ -16,11 +16,15 @@ When you extend the <xref:System.Collections.Generic.IEnumerable%601> interface,
16
16
17
17
An *aggregate* method computes a single value from a set of values. LINQ provides several aggregate methods, including <xref:System.Linq.Enumerable.Average%2A>, <xref:System.Linq.Enumerable.Min%2A>, and <xref:System.Linq.Enumerable.Max%2A>. You can create your own aggregate method by adding an extension method to the <xref:System.Collections.Generic.IEnumerable%601> interface.
18
18
19
-
The following code example shows how to create an extension method called `Median` to compute a median for a sequence of numbers of type `double`.
19
+
Beginning in C# 14, you can declare an *extension block* to contain multiple extension members. You declare an extension block with the keyword `extension` followed by the receiver parameter in parentheses. The following code example shows how to create an extension method called `Median` in an extension block. The method computes a median for a sequence of numbers of type `double`.
You can also add the `this` modifier to a static method to declare an *extension method*. The following code shows the equivalent `Median` extension method:
You call this extension method for any enumerable collection in the same way you call other aggregate methods from the <xref:System.Collections.Generic.IEnumerable%601> interface.
27
+
You call either extension method for any enumerable collection in the same way you call other aggregate methods from the <xref:System.Collections.Generic.IEnumerable%601> interface.
24
28
25
29
The following code example shows how to use the `Median` method for an array of type `double`.
26
30
@@ -58,57 +62,10 @@ You can call this extension method for any enumerable collection just as you wou
The following example shows how to group elements into chunks that represent subsequences of contiguous keys. For example, assume that you're given the following sequence of key-value pairs:
64
-
65
-
|Key | Value |
66
-
|----|--------|
67
-
| A | We |
68
-
| A | think |
69
-
| A | that |
70
-
| B | Linq |
71
-
| C | is |
72
-
| A | really |
73
-
| B | cool |
74
-
| B | ! |
75
-
76
-
The following groups are created in this order:
77
-
78
-
1. We, think, that
79
-
1. Linq
80
-
1. is
81
-
1. really
82
-
1. cool, !
83
-
84
-
The solution is implemented as a thread-safe extension method that returns its results in a streaming manner. It produces its groups as it moves through the source sequence. Unlike the `group` or `orderby` operators, it can begin returning groups to the caller before reading the entire sequence. The following example shows both the extension method and the client code that uses it:
In the presented code of the `ChunkExtensions` class implementation, the `while(true)` loop in the `ChunkBy` method iterates through source sequence and creates a copy of each Chunk. On each pass, the iterator advances to the first element of the next "Chunk", represented by a [`Chunk`](#chunk-class) object, in the source sequence. This loop corresponds to the outer foreach loop that executes the query. In that loop, the code does the following actions:
93
-
94
-
1. Get the key for the current Chunk and assign it to `key` variable. The source iterator consumes the source sequence until it finds an element with a key that doesn't match.
95
-
1. Make a new Chunk (group) object, and store it in `current` variable. It has one GroupItem, a copy of the current source element.
96
-
1. Return that Chunk. A Chunk is an `IGrouping<TKey,TSource>`, which is the return value of the [`ChunkBy`](#chunk-class) method. The Chunk only has the first element in its source sequence. The remaining elements are returned only when the client code foreach's over this chunk. See `Chunk.GetEnumerator` for more info.
97
-
1. Check to see if:
98
-
- The chunk has a copy of all its source elements, or
99
-
- The iterator reached the end of the source sequence.
100
-
1. When the caller has enumerated all the chunk items, the `Chunk.GetEnumerator` method has copied all chunk items. If the `Chunk.GetEnumerator` loop didn't enumerate all elements in the chunk, do it now to avoid corrupting the iterator for clients that might be calling it on a separate thread.
101
-
102
-
### `Chunk` class
103
-
104
-
The `Chunk` class is a contiguous group of one or more source elements that have the same key. A Chunk has a key and a list of ChunkItem objects, which are copies of the elements in the source sequence:
Each `ChunkItem` (represented by `ChunkItem` class) has a reference to the next `ChunkItem` in the list. The list consists of its `head` - which stores the contents of the first source element that belongs with this chunk, and its `tail` - which is an end of the list. The tail is repositioned each time a new `ChunkItem` is added. The tail of the linked list is set to `null` in the `CopyNextChunkElement` method if the key of the next element doesn't match the current chunk's key, or there are no more elements in the source.
65
+
Each example shown in this article has a different *receiver*. That means each method must be declared in a different extension block that specifies the unique receiver. The following code example shows a single static class with three different extension blocks, each of which contains one of the methods defined in this article:
109
66
110
-
The `CopyNextChunkElement` method of the `Chunk` class adds one `ChunkItem` to the current group of items. It tries to advance the iterator on the source sequence. If the `MoveNext()` method returns `false` the iteration is at the end, and `isLastSourceElement` is set to `true`.
The `CopyAllChunkElements` method is called after the end of the last chunk was reached. It checks whether there are more elements in the source sequence. If there are, it returns `true` if the enumerator for this chunk was exhausted. In this method, when the private `DoneCopyingChunk` field is checked for `true`, if isLastSourceElement is `false`, it signals to the outer iterator to continue iterating.
69
+
The final extension block declares a generic extension block. The type parameter for the receiver is declared on the `extension` itself.
113
70
114
-
The inner foreach loop invokes the `GetEnumerator` method of the `Chunk` class. This method stays one element ahead of the client requests. It adds the next element of the chunk only after the client requests the previous last element in the list.
71
+
The preceding example declares one extension member in each extension block. In most cases, you create multiple extension members for the same receiver. In those cases, you should declare the extensions for those members in a single extension block.
0 commit comments