diff --git a/docs/csharp/programming-guide/classes-and-structs/how-to-create-a-new-method-for-an-enumeration.md b/docs/csharp/programming-guide/classes-and-structs/how-to-create-a-new-method-for-an-enumeration.md
index de3d6a49a61bd..1353e1451c036 100644
--- a/docs/csharp/programming-guide/classes-and-structs/how-to-create-a-new-method-for-an-enumeration.md
+++ b/docs/csharp/programming-guide/classes-and-structs/how-to-create-a-new-method-for-an-enumeration.md
@@ -1,7 +1,7 @@
---
title: "How to create a new method for an enumeration"
description: Learn how to use extension methods to add functionality to an enum in C#. This example shows an extension method called Passing for an enum called Grades.
-ms.date: 04/17/2025
+ms.date: 11/25/2025
helpviewer_keywords:
- "enumerations [C#]"
- "extension methods [C#], for enums"
diff --git a/docs/csharp/programming-guide/classes-and-structs/how-to-use-implicitly-typed-local-variables-and-arrays-in-a-query-expression.md b/docs/csharp/programming-guide/classes-and-structs/how-to-use-implicitly-typed-local-variables-and-arrays-in-a-query-expression.md
index c0d8aff8908d1..cc0917b88a140 100644
--- a/docs/csharp/programming-guide/classes-and-structs/how-to-use-implicitly-typed-local-variables-and-arrays-in-a-query-expression.md
+++ b/docs/csharp/programming-guide/classes-and-structs/how-to-use-implicitly-typed-local-variables-and-arrays-in-a-query-expression.md
@@ -1,11 +1,10 @@
---
title: "How to use implicitly typed local variables and arrays in a query expression"
description: Use implicitly typed local variables in C# to have the compiler determine the type of a local variable. You must use them to store anonymous types.
-ms.date: 07/20/2015
+ms.date: 11/25/2025
helpviewer_keywords:
- "implicitly-typed local variables [C#], how to use"
ms.topic: how-to
-ms.assetid: 6b7354d2-af79-427a-b6a8-f74eb8fd0b91
---
# How to use implicitly typed local variables and arrays in a query expression (C# Programming Guide)
@@ -25,6 +24,6 @@ You can use implicitly typed local variables whenever you want the compiler to d
## See also
-- [Extension Methods](./extension-methods.md)
+- [Extension members](./extension-methods.md)
- [LINQ (Language-Integrated Query)](../../linq/index.md)
- [LINQ in C#](../../linq/index.md)
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/how-to-implement-and-call-a-custom-extension-method/Program.cs b/docs/csharp/programming-guide/classes-and-structs/snippets/how-to-implement-and-call-a-custom-extension-method/Program.cs
index 963b4e6c01aaa..5152ded74a133 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/how-to-implement-and-call-a-custom-extension-method/Program.cs
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/how-to-implement-and-call-a-custom-extension-method/Program.cs
@@ -1,4 +1,4 @@
-using CustomExtensions;
+using CustomExtensions;
string s = "The quick brown fox jumped over the lazy dog.";
// Call the method as if it were an
@@ -13,12 +13,14 @@ namespace CustomExtensions
// Extension methods must be defined in a static class.
public static class StringExtension
{
- // This is the extension method.
- // The first parameter takes the "this" modifier
- // and specifies the type for which the method is defined.
- public static int WordCount(this string str)
+ extension(string str)
{
- return str.Split(new char[] {' ', '.','?'}, StringSplitOptions.RemoveEmptyEntries).Length;
+ // This is the extension member.
+ // The `str` parameter is declared on the extension declaration.
+ public int WordCount()
+ {
+ return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
+ }
}
}
}
diff --git a/docs/csharp/programming-guide/classes-and-structs/snippets/how-to-implement-and-call-a-custom-extension-method/how-to-implement-and-call-a-custom-extension-method.csproj b/docs/csharp/programming-guide/classes-and-structs/snippets/how-to-implement-and-call-a-custom-extension-method/how-to-implement-and-call-a-custom-extension-method.csproj
index fd4bd08da2987..ed9781c223ab9 100644
--- a/docs/csharp/programming-guide/classes-and-structs/snippets/how-to-implement-and-call-a-custom-extension-method/how-to-implement-and-call-a-custom-extension-method.csproj
+++ b/docs/csharp/programming-guide/classes-and-structs/snippets/how-to-implement-and-call-a-custom-extension-method/how-to-implement-and-call-a-custom-extension-method.csproj
@@ -2,7 +2,7 @@
Exe
- net9.0
+ net10.0
enable
enable
diff --git a/docs/csharp/programming-guide/generics/constraints-on-type-parameters.md b/docs/csharp/programming-guide/generics/constraints-on-type-parameters.md
index 0adad6ba44ade..8b4dc2c3b56b7 100644
--- a/docs/csharp/programming-guide/generics/constraints-on-type-parameters.md
+++ b/docs/csharp/programming-guide/generics/constraints-on-type-parameters.md
@@ -1,7 +1,7 @@
---
title: "Constraints on type parameters"
description: Learn about constraints on type parameters. Constraints tell the compiler what capabilities a type argument must have.
-ms.date: 10/10/2025
+ms.date: 11/25/2025
f1_keywords:
- "defaultconstraint_CSharpKeyword"
- "notnull_CSharpKeyword"
diff --git a/docs/csharp/programming-guide/generics/snippets/GenericWhereConstraints.cs b/docs/csharp/programming-guide/generics/snippets/GenericWhereConstraints.cs
index 06d9d7ce50141..198d070e0b2d4 100644
--- a/docs/csharp/programming-guide/generics/snippets/GenericWhereConstraints.cs
+++ b/docs/csharp/programming-guide/generics/snippets/GenericWhereConstraints.cs
@@ -175,20 +175,25 @@ unsafe public static byte[] ToByteArray(this T argument) where T : unmanaged
//
//
- public static TDelegate? TypeSafeCombine(this TDelegate source, TDelegate target)
- where TDelegate : System.Delegate
- => Delegate.Combine(source, target) as TDelegate;
+ extension(TDelegate source) where TDelegate : System.Delegate
+ {
+ public TDelegate? TypeSafeCombine(TDelegate target)
+ => Delegate.Combine(source, target) as TDelegate;
+ }
//
//
- public static Dictionary EnumNamedValues() where T : System.Enum
+ extension(T) where T : System.Enum
{
- var result = new Dictionary();
- var values = Enum.GetValues(typeof(T));
+ public static Dictionary EnumNamedValues()
+ {
+ var result = new Dictionary();
+ var values = Enum.GetValues(typeof(T));
- foreach (int item in values)
- result.Add(item, Enum.GetName(typeof(T), item)!);
- return result;
+ foreach (int item in values)
+ result.Add(item, Enum.GetName(typeof(T), item)!);
+ return result;
+ }
}
//
}
diff --git a/docs/csharp/programming-guide/generics/snippets/generics.csproj b/docs/csharp/programming-guide/generics/snippets/generics.csproj
index 9d40194d4ea68..07fc2e7e62dcc 100644
--- a/docs/csharp/programming-guide/generics/snippets/generics.csproj
+++ b/docs/csharp/programming-guide/generics/snippets/generics.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net10.0
enable
enable
true
diff --git a/docs/csharp/toc.yml b/docs/csharp/toc.yml
index 942cf95b66fcd..5324dd7a241eb 100644
--- a/docs/csharp/toc.yml
+++ b/docs/csharp/toc.yml
@@ -558,8 +558,6 @@ items:
href: programming-guide/classes-and-structs/implicitly-typed-local-variables.md
- name: "How to use implicitly typed local variables and arrays in a query expression"
href: programming-guide/classes-and-structs/how-to-use-implicitly-typed-local-variables-and-arrays-in-a-query-expression.md
- - name: Extension Methods
- href: programming-guide/classes-and-structs/extension-methods.md
- name: "How to implement and call a custom extension method"
href: programming-guide/classes-and-structs/how-to-implement-and-call-a-custom-extension-method.md
- name: "How to create a new method for an enumeration"
@@ -580,6 +578,8 @@ items:
href: programming-guide/classes-and-structs/static-constructors.md
- name: "How to write a copy constructor"
href: programming-guide/classes-and-structs/how-to-write-a-copy-constructor.md
+ - name: Extension members
+ href: programming-guide/classes-and-structs/extension-methods.md
- name: Finalizers
href: programming-guide/classes-and-structs/finalizers.md
- name: Object and Collection Initializers
diff --git a/docs/csharp/tutorials/snippets/console-linq/InterimSteps.cs b/docs/csharp/tutorials/snippets/console-linq/InterimSteps.cs
new file mode 100644
index 0000000000000..c307108c66e07
--- /dev/null
+++ b/docs/csharp/tutorials/snippets/console-linq/InterimSteps.cs
@@ -0,0 +1,175 @@
+namespace UnusedCode;
+
+using LinqFaroShuffle;
+internal class InterimSteps
+{
+ //
+ static IEnumerable Suits()
+ {
+ yield return "clubs";
+ yield return "diamonds";
+ yield return "hearts";
+ yield return "spades";
+ }
+
+ static IEnumerable Ranks()
+ {
+ yield return "two";
+ yield return "three";
+ yield return "four";
+ yield return "five";
+ yield return "six";
+ yield return "seven";
+ yield return "eight";
+ yield return "nine";
+ yield return "ten";
+ yield return "jack";
+ yield return "queen";
+ yield return "king";
+ yield return "ace";
+ }
+ //
+
+ private static void InitialMain()
+ {
+ //
+ var startingDeck = from s in Suits()
+ from r in Ranks()
+ select (Suit: s, Rank: r);
+
+ // Display each card that's generated and placed in startingDeck
+ foreach (var card in startingDeck)
+ {
+ Console.WriteLine(card);
+ }
+ //
+
+ //
+ var top = startingDeck.Take(26);
+ var bottom = startingDeck.Skip(26);
+ //
+
+ }
+
+ private void StartShuffling()
+ {
+ var startingDeck = from s in Suits()
+ from r in Ranks()
+ select (Suit: s, Rank: r);
+
+ // Display each card that's generated and placed in startingDeck
+ foreach (var card in startingDeck)
+ {
+ Console.WriteLine(card);
+ }
+
+ var top = startingDeck.Take(26);
+ var bottom = startingDeck.Skip(26);
+
+ //
+ var shuffledDeck = top.InterleaveSequenceWith(bottom);
+
+ foreach (var c in shuffledDeck)
+ {
+ Console.WriteLine(c);
+ }
+ //
+ }
+
+ private void CompareSequences()
+ {
+ //
+ var startingDeck = from s in Suits()
+ from r in Ranks()
+ select (Suit: s, Rank: r);
+
+ // Display each card generated and placed in startingDeck in the console
+ foreach (var card in startingDeck)
+ {
+ Console.WriteLine(card);
+ }
+
+ var top = startingDeck.Take(26);
+ var bottom = startingDeck.Skip(26);
+
+ var shuffledDeck = top.InterleaveSequenceWith(bottom);
+
+ var times = 0;
+ // Re-use the shuffle variable from earlier, or you can make a new one
+ shuffledDeck = startingDeck;
+ do
+ {
+ shuffledDeck = shuffledDeck.Take(26).InterleaveSequenceWith(shuffledDeck.Skip(26));
+
+ foreach (var card in shuffledDeck)
+ {
+ Console.WriteLine(card);
+ }
+ Console.WriteLine();
+ times++;
+
+ } while (!startingDeck.SequenceEquals(shuffledDeck));
+
+ Console.WriteLine(times);
+ //
+ }
+
+ private void AddLogging()
+ {
+ //
+ var startingDeck = (from s in Suits().LogQuery("Suit Generation")
+ from r in Ranks().LogQuery("Rank Generation")
+ select (Suit: s, Rank: r)).LogQuery("Starting Deck");
+
+ foreach (var c in startingDeck)
+ {
+ Console.WriteLine(c);
+ }
+
+ Console.WriteLine();
+ var times = 0;
+ var shuffle = startingDeck;
+
+ do
+ {
+ // Out shuffle
+ /*
+ shuffle = shuffle.Take(26)
+ .LogQuery("Top Half")
+ .InterleaveSequenceWith(shuffle.Skip(26)
+ .LogQuery("Bottom Half"))
+ .LogQuery("Shuffle");
+ */
+
+ // In shuffle
+ shuffle = shuffle.Skip(26).LogQuery("Bottom Half")
+ .InterleaveSequenceWith(shuffle.Take(26).LogQuery("Top Half"))
+ .LogQuery("Shuffle");
+
+ foreach (var c in shuffle)
+ {
+ Console.WriteLine(c);
+ }
+
+ times++;
+ Console.WriteLine(times);
+ } while (!startingDeck.SequenceEquals(shuffle));
+
+ Console.WriteLine(times);
+ //
+ }
+}
+
+//
+public static class CardExtensions
+{
+ extension(IEnumerable sequence)
+ {
+ public IEnumerable InterleaveSequenceWith(IEnumerable second)
+ {
+ // Your implementation goes here
+ return default;
+ }
+ }
+}
+//
diff --git a/samples/snippets/csharp/getting-started/console-linq/console-linq.csproj b/docs/csharp/tutorials/snippets/console-linq/LInqFaroShuffle.csproj
similarity index 62%
rename from samples/snippets/csharp/getting-started/console-linq/console-linq.csproj
rename to docs/csharp/tutorials/snippets/console-linq/LInqFaroShuffle.csproj
index af31fefa23aa5..0ece068f6df1a 100644
--- a/samples/snippets/csharp/getting-started/console-linq/console-linq.csproj
+++ b/docs/csharp/tutorials/snippets/console-linq/LInqFaroShuffle.csproj
@@ -2,8 +2,9 @@
Exe
- net8.0
+ net10.0
enable
+ enable
diff --git a/docs/csharp/tutorials/snippets/console-linq/Program.cs b/docs/csharp/tutorials/snippets/console-linq/Program.cs
new file mode 100644
index 0000000000000..fb1527fc5552f
--- /dev/null
+++ b/docs/csharp/tutorials/snippets/console-linq/Program.cs
@@ -0,0 +1,83 @@
+using LinqFaroShuffle;
+
+//
+IEnumerable suits() => (Enum.GetValues(typeof(Suit)) as IEnumerable)!;
+//
+
+//
+IEnumerable ranks() => (Enum.GetValues(typeof(Rank)) as IEnumerable)!;
+//
+
+//
+var startingDeck = (from s in suits().LogQuery("Suit Generation")
+ from r in ranks().LogQuery("Value Generation")
+ select new { Suit = s, Rank = r })
+ .LogQuery("Starting Deck")
+ .ToArray();
+
+foreach (var c in startingDeck)
+{
+ Console.WriteLine(c);
+}
+
+Console.WriteLine();
+
+var times = 0;
+var shuffle = startingDeck;
+
+do
+{
+ /*
+ shuffle = shuffle.Take(26)
+ .LogQuery("Top Half")
+ .InterleaveSequenceWith(shuffle.Skip(26).LogQuery("Bottom Half"))
+ .LogQuery("Shuffle")
+ .ToArray();
+ */
+
+ shuffle = shuffle.Skip(26)
+ .LogQuery("Bottom Half")
+ .InterleaveSequenceWith(shuffle.Take(26).LogQuery("Top Half"))
+ .LogQuery("Shuffle")
+ .ToArray();
+
+ foreach (var c in shuffle)
+ {
+ Console.WriteLine(c);
+ }
+
+ times++;
+ Console.WriteLine(times);
+} while (!startingDeck.SequenceEquals(shuffle));
+
+Console.WriteLine(times);
+//
+
+//
+public enum Suit
+{
+ Clubs,
+ Diamonds,
+ Hearts,
+ Spades
+}
+//
+
+//
+public enum Rank
+{
+ Two,
+ Three,
+ Four,
+ Five,
+ Six,
+ Seven,
+ Eight,
+ Nine,
+ Ten,
+ Jack,
+ Queen,
+ King,
+ Ace
+}
+//
diff --git a/samples/snippets/csharp/getting-started/console-linq/README.md b/docs/csharp/tutorials/snippets/console-linq/README.md
similarity index 100%
rename from samples/snippets/csharp/getting-started/console-linq/README.md
rename to docs/csharp/tutorials/snippets/console-linq/README.md
diff --git a/samples/snippets/csharp/getting-started/console-linq/extensions.cs b/docs/csharp/tutorials/snippets/console-linq/extensions.cs
similarity index 57%
rename from samples/snippets/csharp/getting-started/console-linq/extensions.cs
rename to docs/csharp/tutorials/snippets/console-linq/extensions.cs
index 432a05c691e71..88a2c025125ec 100644
--- a/samples/snippets/csharp/getting-started/console-linq/extensions.cs
+++ b/docs/csharp/tutorials/snippets/console-linq/extensions.cs
@@ -1,15 +1,13 @@
-using System.Collections.Generic;
-using System.IO;
+namespace LinqFaroShuffle;
-namespace LinqFaroShuffle
+public static class CardExtensions
{
- public static class Extensions
+ extension(IEnumerable sequence)
{
- #region snippet1
- public static IEnumerable InterleaveSequenceWith
- (this IEnumerable first, IEnumerable second)
+ //
+ public IEnumerable InterleaveSequenceWith(IEnumerable second)
{
- var firstIter = first.GetEnumerator();
+ var firstIter = sequence.GetEnumerator();
var secondIter = second.GetEnumerator();
while (firstIter.MoveNext() && secondIter.MoveNext())
@@ -18,13 +16,12 @@ public static IEnumerable InterleaveSequenceWith
yield return secondIter.Current;
}
}
- #endregion
+ //
- #region snippet2
- public static bool SequenceEquals
- (this IEnumerable first, IEnumerable second)
+ //
+ public bool SequenceEquals(IEnumerable second)
{
- var firstIter = first.GetEnumerator();
+ var firstIter = sequence.GetEnumerator();
var secondIter = second.GetEnumerator();
while ((firstIter?.MoveNext() == true) && secondIter.MoveNext())
@@ -37,11 +34,10 @@ public static bool SequenceEquals
return true;
}
- #endregion
+ //
- #region snippet3
- public static IEnumerable LogQuery
- (this IEnumerable sequence, string tag)
+ //
+ public IEnumerable LogQuery(string tag)
{
// File.AppendText creates a new file if the file doesn't exist.
using (var writer = File.AppendText("debug.log"))
@@ -51,6 +47,6 @@ public static IEnumerable LogQuery
return sequence;
}
- #endregion
+ //
}
}
diff --git a/docs/csharp/tutorials/snippets/console-linq/playingcard.cs b/docs/csharp/tutorials/snippets/console-linq/playingcard.cs
new file mode 100644
index 0000000000000..1096d7db4bca3
--- /dev/null
+++ b/docs/csharp/tutorials/snippets/console-linq/playingcard.cs
@@ -0,0 +1,5 @@
+namespace LinqFaroShuffle;
+
+//
+public sealed record PlayingCard(Suit CardSuit, Rank CardRank);
+//
diff --git a/docs/csharp/tutorials/working-with-linq.md b/docs/csharp/tutorials/working-with-linq.md
index c8ffb58e4f5fa..91162bbbca7e6 100644
--- a/docs/csharp/tutorials/working-with-linq.md
+++ b/docs/csharp/tutorials/working-with-linq.md
@@ -1,26 +1,25 @@
---
title: Working with LINQ
description: This tutorial teaches you how to generate sequences with LINQ, write methods for use in LINQ queries, and distinguish between eager and lazy evaluation.
-ms.date: 10/29/2018
+ms.date: 11/25/2025
ms.subservice: csharp-linq
-ms.assetid: 0db12548-82cb-4903-ac88-13103d70aa77
+ai-usage: ai-assisted
---
-
# Work with Language-Integrated Query (LINQ)
## Introduction
-This tutorial teaches you features in .NET Core and the C# language. You’ll learn how to:
+This tutorial teaches you features in .NET and the C# language. You learn how to:
- Generate sequences with LINQ.
-- Write methods that can be easily used in LINQ queries.
+- Write methods that you can easily use in LINQ queries.
- Distinguish between eager and lazy evaluation.
-You'll learn these techniques by building an application that demonstrates one of the basic skills of any magician: the [faro shuffle](https://en.wikipedia.org/wiki/Faro_shuffle). Briefly, a faro shuffle is a technique where you split a card deck exactly in half, then the shuffle interleaves each one card from each half to rebuild the original deck.
+You learn these techniques by building an application that demonstrates one of the basic skills of any magician: the [faro shuffle](https://en.wikipedia.org/wiki/Faro_shuffle). A faro shuffle is a technique where you split a card deck exactly in half, and then the shuffle interleaves each card from each half to rebuild the original deck.
Magicians use this technique because every card is in a known location after each shuffle, and the order is a repeating pattern.
-For your purposes, it is a light hearted look at manipulating sequences of data. The application you'll build constructs a card deck and then performs a sequence of shuffles, writing the sequence out each time. You'll also compare the updated order to the original order.
+This tutorial offers a lighthearted look at manipulating sequences of data. The application constructs a card deck, performs a sequence of shuffles, and writes the sequence out each time. It also compares the updated order to the original order.
This tutorial has multiple steps. After each step, you can run the application and see the progress. You can also see the [completed sample](https://github.com/dotnet/samples/blob/main/csharp/getting-started/console-linq) in the dotnet/samples GitHub repository. For download instructions, see [Samples and Tutorials](../../samples-and-tutorials/index.md#view-and-download-samples).
@@ -28,331 +27,147 @@ This tutorial has multiple steps. After each step, you can run the application a
[!INCLUDE [Prerequisites](../../../includes/prerequisites-basic.md)]
-## Create the Application
+## Create the application
-The first step is to create a new application. Open a command prompt and create a new directory for your application. Make that the current directory. Type the command `dotnet new console` at the command prompt. This creates the starter files for a basic "Hello World" application.
+Create a new application. Open a command prompt and create a new directory for your application. Make that the current directory. Type the command `dotnet new console -o LinqFaroShuffle` at the command prompt. This command creates the starter files for a basic "Hello World" application.
If you've never used C# before, [this tutorial](console-teleprompter.md) explains the structure of a C# program. You can read that and then return here to learn more about LINQ.
-## Create the Data Set
-
-Before you begin, make sure that the following lines are at the top of the `Program.cs` file generated by `dotnet new console`:
-
-```csharp
-// Program.cs
-using System;
-using System.Collections.Generic;
-using System.Linq;
-```
-
-If these three lines (`using` directives) aren't at the top of the file, your program might not compile.
+## Create the data set
> [!TIP]
> For this tutorial, you can organize your code in a namespace called `LinqFaroShuffle` to match the sample code, or you can use the default global namespace. If you choose to use a namespace, make sure all your classes and methods are consistently within the same namespace, or add appropriate `using` statements as needed.
-Now that you have all of the references that you'll need, consider what constitutes a deck of cards. Commonly, a deck of playing cards has four suits, and each suit has thirteen values. Normally, you might consider creating a `Card` class right off the bat and populating a collection of `Card` objects by hand. With LINQ, you can be more concise than the usual way of dealing with creating a deck of cards. Instead of creating a `Card` class, you can create two sequences to represent suits and ranks, respectively. You'll create a really simple pair of [*iterator methods*](../iterators.md#enumeration-sources-with-iterator-methods) that will generate the ranks and suits as s of strings:
+Consider what constitutes a deck of cards. A deck of playing cards has four suits, and each suit has 13 values. Normally, you might consider creating a `Card` class right away and populating a collection of `Card` objects by hand. With LINQ, you can be more concise than the usual way of creating a deck of cards. Instead of creating a `Card` class, create two sequences to represent suits and ranks. Create a pair of [*iterator methods*](../iterators.md#enumeration-sources-with-iterator-methods) that generate the ranks and suits as s of strings:
-```csharp
-// Program.cs
-// The Main() method
-
-static IEnumerable Suits()
-{
- yield return "clubs";
- yield return "diamonds";
- yield return "hearts";
- yield return "spades";
-}
-
-static IEnumerable Ranks()
-{
- yield return "two";
- yield return "three";
- yield return "four";
- yield return "five";
- yield return "six";
- yield return "seven";
- yield return "eight";
- yield return "nine";
- yield return "ten";
- yield return "jack";
- yield return "queen";
- yield return "king";
- yield return "ace";
-}
-```
+:::code source="snippets/console-linq/InterimSteps.cs" id="StepOne":::
-Place these underneath the `Main` method in your `Program.cs` file. These two methods both utilize the `yield return` syntax to produce a sequence as they run. The compiler builds an object that implements and generates the sequence of strings as they are requested.
+Place these methods under the `Console.WriteLine` statement in your `Program.cs` file. These two methods both use the `yield return` syntax to produce a sequence as they run. The compiler builds an object that implements and generates the sequence of strings as they're requested.
-Now, use these iterator methods to create the deck of cards. You'll place the LINQ query in our `Main` method. Here's a look at it:
+Now, use these iterator methods to create the deck of cards. Place the LINQ query at the top of the `Program.cs` file. Here's what it looks like:
-```csharp
-// Program.cs
-static void Main(string[] args)
-{
- var startingDeck = from s in Suits()
- from r in Ranks()
- select new { Suit = s, Rank = r };
-
- // Display each card that we've generated and placed in startingDeck in the console
- foreach (var card in startingDeck)
- {
- Console.WriteLine(card);
- }
-}
-```
+:::code source="snippets/console-linq/InterimSteps.cs" id="StepTwo":::
-The multiple `from` clauses produce a , which creates a single sequence from combining each element in the first sequence with each element in the second sequence. The order is important for our purposes. The first element in the first source sequence (Suits) is combined with every element in the second sequence (Ranks). This produces all thirteen cards of first suit. That process is repeated with each element in the first sequence (Suits). The end result is a deck of cards ordered by suits, followed by values.
+The multiple `from` clauses produce a , which creates a single sequence from combining each element in the first sequence with each element in the second sequence. The order is important for this example. The first element in the first source sequence (Suits) is combined with every element in the second sequence (Ranks). This process produces all 13 cards of first suit. That process is repeated with each element in the first sequence (Suits). The end result is a deck of cards ordered by suits, followed by values.
-It's important to keep in mind that whether you choose to write your LINQ in the query syntax used above or use method syntax instead, it's always possible to go from one form of syntax to the other. The above query written in query syntax can be written in method syntax as:
+Keep in mind that whether you write your LINQ in the query syntax used in the preceding sample or use method syntax instead, it's always possible to go from one form of syntax to the other. The preceding query written in query syntax can be written in method syntax as:
```csharp
-var startingDeck = Suits().SelectMany(suit => Ranks().Select(rank => new { Suit = suit, Rank = rank }));
+var startingDeck = Suits().SelectMany(suit => Ranks().Select(rank => (Suit: suit, Rank: rank )));
```
-The compiler translates LINQ statements written with query syntax into the equivalent method call syntax. Therefore, regardless of your syntax choice, the two versions of the query produce the same result. Choose which syntax works best for your situation: for instance, if you're working in a team where some of the members have difficulty with method syntax, try to prefer using query syntax.
+The compiler translates LINQ statements written with query syntax into the equivalent method call syntax. Therefore, regardless of your syntax choice, the two versions of the query produce the same result. Choose the syntax that works best for your situation. For instance, if you're working in a team where some members have difficulty with method syntax, try to prefer using query syntax.
-Go ahead and run the sample you've built at this point. It will display all 52 cards in the deck. You may find it very helpful to run this sample under a debugger to observe how the `Suits()` and `Ranks()` methods execute. You can clearly see that each string in each sequence is generated only as it is needed.
+Run the sample you built at this point. It displays all 52 cards in the deck. You might find it helpful to run this sample under a debugger to observe how the `Suits()` and `Ranks()` methods execute. You can clearly see that each string in each sequence is generated only as needed.

-## Manipulate the Order
+## Manipulate the order
-Next, focus on how you're going to shuffle the cards in the deck. The first step in any good shuffle is to split the deck in two. The and methods that are part of the LINQ APIs provide that feature for you. Place them underneath the `foreach` loop:
+Next, focus on how you shuffle the cards in the deck. The first step in any good shuffle is to split the deck in two. The and methods that are part of the LINQ APIs provide that feature. Place them following the `foreach` loop:
-```csharp
-// Program.cs
-public static void Main(string[] args)
-{
- var startingDeck = from s in Suits()
- from r in Ranks()
- select new { Suit = s, Rank = r };
-
- foreach (var c in startingDeck)
- {
- Console.WriteLine(c);
- }
-
- // 52 cards in a deck, so 52 / 2 = 26
- var top = startingDeck.Take(26);
- var bottom = startingDeck.Skip(26);
-}
-```
+:::code source="snippets/console-linq/InterimSteps.cs" id="StepThree":::
-However, there's no shuffle method to take advantage of in the standard library, so you'll have to write your own. The shuffle method you'll be creating illustrates several techniques that you'll use with LINQ-based programs, so each part of this process will be explained in steps.
+However, there's no shuffle method to take advantage of in the standard library, so you need to write your own. The shuffle method you create illustrates several techniques that you use with LINQ-based programs, so each part of this process is explained in steps.
-In order to add some functionality to how you interact with the you'll get back from LINQ queries, you'll need to write some special kinds of methods called [extension methods](../programming-guide/classes-and-structs/extension-methods.md). Briefly, an extension method is a special purpose *static method* that adds new functionality to an already-existing type without having to modify the original type you want to add functionality to.
+To add functionality to how you interact with the results of LINQ queries, you write some special kinds of methods called [extension methods](../programming-guide/classes-and-structs/extension-methods.md). An extension method is a special purpose *static method* that adds new functionality to an already-existing type without having to modify the original type you want to add functionality to.
Give your extension methods a new home by adding a new *static* class file to your program called `Extensions.cs`, and then start building out the first extension method:
-```csharp
-// Extensions.cs
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace LinqFaroShuffle
-{
- public static class Extensions
- {
- public static IEnumerable InterleaveSequenceWith(this IEnumerable first, IEnumerable second)
- {
- // Your implementation will go here soon enough
- }
- }
-}
-```
+:::code source="snippets/console-linq/InterimSteps.cs" id="StepFour":::
> [!NOTE]
> If you're using an editor other than Visual Studio (such as Visual Studio Code), you might need to add `using LinqFaroShuffle;` to the top of your _Program.cs_ file for the extension methods to be accessible. Visual Studio automatically adds this using statement, but other editors might not.
-Look at the method signature for a moment, specifically the parameters:
+The `extension` container specifies the type being extended. The `extension` node declares the type and name of the *receiver parameter* for all members inside the `extension` container. In this example, you're extending `IEnumerable`, and the parameter is named `sequence`.
+
+Extension member declarations appear as though they're members of the receiver type:
```csharp
-public static IEnumerable InterleaveSequenceWith (this IEnumerable first, IEnumerable second)
+public IEnumerable InterleaveSequenceWith(IEnumerable second)
```
-You can see the addition of the `this` modifier on the first argument to the method. That means you call the method as though it were a member method of the type of the first argument. This method declaration also follows a standard idiom where the input and output types are `IEnumerable`. That practice enables LINQ methods to be chained together to perform more complex queries.
+You call the method as though it were a member method of the extended type. This method declaration also follows a standard idiom where the input and output types are `IEnumerable`. That practice enables LINQ methods to be chained together to perform more complex queries.
-Naturally, since you split the deck into halves, you'll need to join those halves together. In code, this means you'll be enumerating both of the sequences you acquired through and at once, *`interleaving`* the elements, and creating one sequence: your now-shuffled deck of cards. Writing a LINQ method that works with two sequences requires that you understand how works.
+Since you split the deck into halves, you need to join those halves together. In code, this means you enumerate both of the sequences you acquired through and at once, *interleaving* the elements, and creating one sequence: your now-shuffled deck of cards. Writing a LINQ method that works with two sequences requires that you understand how works.
-The interface has one method: . The object returned by has a method to move to the next element, and a property that retrieves the current element in the sequence. You will use those two members to enumerate the collection and return the elements. This Interleave method will be an iterator method, so instead of building a collection and returning the collection, you'll use the `yield return` syntax shown above.
+The interface has one method: . The object returned by has a method to move to the next element and a property that retrieves the current element in the sequence. You use those two members to enumerate the collection and return the elements. This Interleave method is an iterator method, so instead of building a collection and returning the collection, you use the `yield return` syntax shown in the preceding code.
Here's the implementation of that method:
-[!CODE-csharp[InterleaveSequenceWith](../../../samples/snippets/csharp/getting-started/console-linq/extensions.cs?name=snippet1)]
+:::code source="snippets/console-linq/extensions.cs" id="snippet1":::
-Now that you've written this method, go back to the `Main` method and shuffle the deck once:
+Now that you wrote this method, go back to the `Main` method and shuffle the deck once:
-```csharp
-// Program.cs
-public static void Main(string[] args)
-{
- var startingDeck = from s in Suits()
- from r in Ranks()
- select new { Suit = s, Rank = r };
-
- foreach (var c in startingDeck)
- {
- Console.WriteLine(c);
- }
-
- var top = startingDeck.Take(26);
- var bottom = startingDeck.Skip(26);
- var shuffle = top.InterleaveSequenceWith(bottom);
-
- foreach (var c in shuffle)
- {
- Console.WriteLine(c);
- }
-}
-```
+:::code source="snippets/console-linq/InterimSteps.cs" id="StepFive":::
## Comparisons
-How many shuffles it takes to set the deck back to its original order? To find out, you'll need to write a method that determines if two sequences are equal. After you have that method, you'll need to place the code that shuffles the deck in a loop, and check to see when the deck is back in order.
+Determine how many shuffles it takes to set the deck back to its original order. To find out, write a method that determines if two sequences are equal. After you have that method, place the code that shuffles the deck in a loop, and check to see when the deck is back in order.
-Writing a method to determine if the two sequences are equal should be straightforward. It's a similar structure to the method you wrote to shuffle the deck. Only this time, instead of `yield return`ing each element, you'll compare the matching elements of each sequence. When the entire sequence has been enumerated, if every element matches, the sequences are the same:
+Writing a method to determine if the two sequences are equal should be straightforward. It's a similar structure to the method you wrote to shuffle the deck. However, this time, instead of using `yield return` for each element, you compare the matching elements of each sequence. When the entire sequence is enumerated, if every element matches, the sequences are the same:
-[!CODE-csharp[SequenceEquals](../../../samples/snippets/csharp/getting-started/console-linq/extensions.cs?name=snippet2)]
+:::code source="snippets/console-linq/extensions.cs" id="snippet2":::
-This shows a second LINQ idiom: terminal methods. They take a sequence as input (or in this case, two sequences), and return a single scalar value. When using terminal methods, they are always the final method in a chain of methods for a LINQ query, hence the name "terminal".
+This method shows a second LINQ idiom: terminal methods. They take a sequence as input (or in this case, two sequences) and return a single scalar value. When you use terminal methods, they're always the final method in a chain of methods for a LINQ query.
-You can see this in action when you use it to determine when the deck is back in its original order. Put the shuffle code inside a loop, and stop when the sequence is back in its original order by applying the `SequenceEquals()` method. You can see it would always be the final method in any query, because it returns a single value instead of a sequence:
+You can see this in action when you use it to determine when the deck is back in its original order. Put the shuffle code inside a loop, and stop when the sequence is back in its original order by applying the `SequenceEquals()` method. You can see it would always be the final method in any query because it returns a single value instead of a sequence:
-```csharp
-// Program.cs
-static void Main(string[] args)
-{
- // Query for building the deck
-
- // Shuffling using InterleaveSequenceWith();
-
- var times = 0;
- // We can re-use the shuffle variable from earlier, or you can make a new one
- shuffle = startingDeck;
- do
- {
- shuffle = shuffle.Take(26).InterleaveSequenceWith(shuffle.Skip(26));
-
- foreach (var card in shuffle)
- {
- Console.WriteLine(card);
- }
- Console.WriteLine();
- times++;
-
- } while (!startingDeck.SequenceEquals(shuffle));
-
- Console.WriteLine(times);
-}
-```
+:::code source="snippets/console-linq/InterimSteps.cs" id="StepSix":::
-Run the code you've got so far and take note of how the deck rearranges on each shuffle. After 8 shuffles (iterations of the do-while loop), the deck returns to the original configuration it was in when you first created it from the starting LINQ query.
+Run the code you built so far and notice how the deck rearranges on each shuffle. After 8 shuffles (iterations of the do-while loop), the deck returns to the original configuration it was in when you first created it from the starting LINQ query.
## Optimizations
-The sample you've built so far executes an *out shuffle*, where the top and bottom cards stay the same on each run. Let's make one change: we'll use an *in shuffle* instead, where all 52 cards change position. For an in shuffle, you interleave the deck so that the first card in the bottom half becomes the first card in the deck. That means the last card in the top half becomes the bottom card. This is a simple change to a singular line of code. Update the current shuffle query by switching the positions of and . This will change the order of the top and bottom halves of the deck:
+The sample you built so far executes an *out shuffle*, where the top and bottom cards stay the same on each run. Let's make one change: use an *in shuffle* instead, where all 52 cards change position. For an in shuffle, you interleave the deck so that the first card in the bottom half becomes the first card in the deck. That means the last card in the top half becomes the bottom card. This change requires one line of code. Update the current shuffle query by switching the positions of and . This change switches the order of the top and bottom halves of the deck:
```csharp
-shuffle = shuffle.Skip(26).InterleaveSequenceWith(shuffle.Take(26));
+shuffledDeck = shuffledDeck.Skip(26).InterleaveSequenceWith(shuffledDeck.Take(26));
```
-Run the program again, and you'll see that it takes 52 iterations for the deck to reorder itself. You'll also start to notice some serious performance degradations as the program continues to run.
-
-There are a number of reasons for this. You can tackle one of the major causes of this performance drop: inefficient use of [*lazy evaluation*](../../standard/linq/deferred-execution-lazy-evaluation.md).
+Run the program again, and you see that it takes 52 iterations for the deck to reorder itself. You also notice some serious performance degradation as the program continues to run.
-Briefly, lazy evaluation states that the evaluation of a statement is not performed until its value is needed. LINQ queries are statements that are evaluated lazily. The sequences are generated only as the elements are requested. Usually, that's a major benefit of LINQ. However, in a use such as this program, this causes exponential growth in execution time.
+There are several reasons for this performance drop. You can tackle one of the major causes: inefficient use of [*lazy evaluation*](../../standard/linq/deferred-execution-lazy-evaluation.md).
-Remember that we generated the original deck using a LINQ query. Each shuffle is generated by performing three LINQ queries on the previous deck. All these are performed lazily. That also means they are performed again each time the sequence is requested. By the time you get to the 52nd iteration, you're regenerating the original deck many, many times. Let's write a log to demonstrate this behavior. Then, you'll fix it.
+Lazy evaluation states that the evaluation of a statement isn't performed until its value is needed. LINQ queries are statements that are evaluated lazily. The sequences are generated only as the elements are requested. Usually, that's a major benefit of LINQ. However, in a program like this one, lazy evaluation causes exponential growth in execution time.
-In your `Extensions.cs` file, type in or copy the method below. This extension method creates a new file called `debug.log` within your project directory and records what query is currently being executed to the log file. This extension method can be appended to any query to mark that the query executed.
+Remember that you generated the original deck using a LINQ query. Each shuffle is generated by performing three LINQ queries on the previous deck. All these queries are performed lazily. That also means they're performed again each time the sequence is requested. By the time you get to the 52nd iteration, you're regenerating the original deck many times. Write a log to demonstrate this behavior. Once you gather data, you can improve performance.
-[!CODE-csharp[LogQuery](../../../samples/snippets/csharp/getting-started/console-linq/extensions.cs?name=snippet3)]
+In your `Extensions.cs` file, type in or copy the method in the following code sample. This extension method creates a new file called `debug.log` within your project directory and records what query is currently being executed to the log file. Append this extension method to any query to mark that the query executed.
-You will see a red squiggle under `File`, meaning it doesn't exist. It won't compile, since the compiler doesn't know what `File` is. To solve this problem, make sure to add the following line of code under the very first line in `Extensions.cs`:
-
-```csharp
-using System.IO;
-```
-
-This should solve the issue and the red error disappears.
+:::code source="snippets/console-linq/extensions.cs" id="snippet3":::
Next, instrument the definition of each query with a log message:
-```csharp
-// Program.cs
-public static void Main(string[] args)
-{
- var startingDeck = (from s in Suits().LogQuery("Suit Generation")
- from r in Ranks().LogQuery("Rank Generation")
- select new { Suit = s, Rank = r }).LogQuery("Starting Deck");
-
- foreach (var c in startingDeck)
- {
- Console.WriteLine(c);
- }
-
- Console.WriteLine();
- var times = 0;
- var shuffle = startingDeck;
-
- do
- {
- // Out shuffle
- /*
- shuffle = shuffle.Take(26)
- .LogQuery("Top Half")
- .InterleaveSequenceWith(shuffle.Skip(26)
- .LogQuery("Bottom Half"))
- .LogQuery("Shuffle");
- */
-
- // In shuffle
- shuffle = shuffle.Skip(26).LogQuery("Bottom Half")
- .InterleaveSequenceWith(shuffle.Take(26).LogQuery("Top Half"))
- .LogQuery("Shuffle");
-
- foreach (var c in shuffle)
- {
- Console.WriteLine(c);
- }
-
- times++;
- Console.WriteLine(times);
- } while (!startingDeck.SequenceEquals(shuffle));
-
- Console.WriteLine(times);
-}
-```
+:::code source="snippets/console-linq/InterimSteps.cs" id="StepSeven":::
-Notice that you don't log every time you access a query. You log only when you create the original query. The program still takes a long time to run, but now you can see why. If you run out of patience running the in shuffle with logging turned on, switch back to the out shuffle. You'll still see the lazy evaluation effects. In one run, it executes 2592 queries, including all the value and suit generation.
+Notice that you don't log every time you access a query. You log only when you create the original query. The program still takes a long time to run, but now you can see why. If you run out of patience running the in shuffle with logging turned on, switch back to the out shuffle. You still see the lazy evaluation effects. In one run, it executes 2,592 queries, including the value and suit generation.
-You can improve the performance of the code here to reduce the number of executions you make. A simple fix you can make is to *cache* the results of the original LINQ query that constructs the deck of cards. Currently, you're executing the queries again and again every time the do-while loop goes through an iteration, re-constructing the deck of cards and reshuffling it every time. To cache the deck of cards, you can leverage the LINQ methods and ; when you append them to the queries, they'll perform the same actions you've told them to, but now they'll store the results in an array or a list, depending on which method you choose to call. Append the LINQ method to both queries and run the program again:
+You can improve the performance of the code to reduce the number of executions you make. A simple fix is to *cache* the results of the original LINQ query that constructs the deck of cards. Currently, you're executing the queries again and again every time the do-while loop goes through an iteration, reconstructing the deck of cards and reshuffling it every time. To cache the deck of cards, apply the LINQ methods and . When you append them to the queries, they perform the same actions you told them to, but now they store the results in an array or a list, depending on which method you choose to call. Append the LINQ method to both queries and run the program again:
-[!CODE-csharp[Main](../../../samples/snippets/csharp/getting-started/console-linq/Program.cs?name=snippet1)]
+:::code source="snippets/console-linq/Program.cs" id="snippet1":::
-Now the out shuffle is down to 30 queries. Run again with the in shuffle and you'll see similar improvements: it now executes 162 queries.
+Now the out shuffle is down to 30 queries. Run again with the in shuffle and you see similar improvements: it now executes 162 queries.
-Please note that this example is **designed** to highlight the use cases where lazy evaluation can cause performance difficulties. While it's important to see where lazy evaluation can impact code performance, it's equally important to understand that not all queries should run eagerly. The performance hit you incur without using is because each new arrangement of the deck of cards is built from the previous arrangement. Using lazy evaluation means each new deck configuration is built from the original deck, even executing the code that built the `startingDeck`. That causes a large amount of extra work.
+This example is **designed** to highlight the use cases where lazy evaluation can cause performance difficulties. While it's important to see where lazy evaluation can impact code performance, it's equally important to understand that not all queries should run eagerly. The performance hit you incur without using is because each new arrangement of the deck of cards is built from the previous arrangement. Using lazy evaluation means each new deck configuration is built from the original deck, even executing the code that built the `startingDeck`. That causes a large amount of extra work.
-In practice, some algorithms run well using eager evaluation, and others run well using lazy evaluation. For daily usage, lazy evaluation is usually a better choice when the data source is a separate process, like a database engine. For databases, lazy evaluation allows more complex queries to execute only one round trip to the database process and back to the rest of your code. LINQ is flexible whether you choose to utilize lazy or eager evaluation, so measure your processes and pick whichever kind of evaluation gives you the best performance.
+In practice, some algorithms run well using eager evaluation, and others run well using lazy evaluation. For daily usage, lazy evaluation is usually a better choice when the data source is a separate process, like a database engine. For databases, lazy evaluation allows more complex queries to execute only one round trip to the database process and back to the rest of your code. LINQ is flexible whether you choose to use lazy or eager evaluation, so measure your processes and pick whichever evaluation gives you the best performance.
## Conclusion
In this project, you covered:
-- using LINQ queries to aggregate data into a meaningful sequence
-- writing Extension methods to add our own custom functionality to LINQ queries
-- locating areas in our code where our LINQ queries might run into performance issues like degraded speed
-- lazy and eager evaluation in regards to LINQ queries and the implications they might have on query performance
+- Using LINQ queries to aggregate data into a meaningful sequence.
+- Writing extension methods to add custom functionality to LINQ queries.
+- Locating areas in code where LINQ queries might run into performance issues like degraded speed.
+- Lazy and eager evaluation in LINQ queries and the implications they might have on query performance.
-Aside from LINQ, you learned a bit about a technique magicians use for card tricks. Magicians use the Faro shuffle because they can control where every card moves in the deck. Now that you know, don't spoil it for everyone else!
+Aside from LINQ, you learned about a technique magicians use for card tricks. Magicians use the faro shuffle because they can control where every card moves in the deck. Now that you know, don't spoil it for everyone else!
For more information on LINQ, see:
- [Introduction to LINQ](../linq/index.md)
-- [Basic LINQ Query Operations (C#)](../linq/standard-query-operators/index.md)
-- [Data Transformations With LINQ (C#)](../linq/standard-query-operators/index.md)
-- [Query Syntax and Method Syntax in LINQ (C#)](../linq/get-started/write-linq-queries.md)
-- [C# Features That Support LINQ](../linq/get-started/features-that-support-linq.md)
+- [Basic LINQ query operations (C#)](../linq/standard-query-operators/index.md)
+- [Data transformations with LINQ (C#)](../linq/standard-query-operators/index.md)
+- [Query syntax and method syntax in LINQ (C#)](../linq/get-started/write-linq-queries.md)
+- [C# features that support LINQ](../linq/get-started/features-that-support-linq.md)
diff --git a/samples/snippets/csharp/getting-started/console-linq/Program.cs b/samples/snippets/csharp/getting-started/console-linq/Program.cs
deleted file mode 100644
index 5898f400b8b84..0000000000000
--- a/samples/snippets/csharp/getting-started/console-linq/Program.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace LinqFaroShuffle
-{
- #region snippet2
- public enum Suit
- {
- Clubs,
- Diamonds,
- Hearts,
- Spades
- }
- #endregion
-
- #region snippet3
- public enum Rank
- {
- Two,
- Three,
- Four,
- Five,
- Six,
- Seven,
- Eight,
- Nine,
- Ten,
- Jack,
- Queen,
- King,
- Ace
- }
- #endregion
-
- public class Program
- {
- #region snippet4
- static IEnumerable Suits() => (Enum.GetValues(typeof(Suit)) as IEnumerable)!;
- #endregion
-
- #region snippet5
- static IEnumerable Ranks() => (Enum.GetValues(typeof(Rank)) as IEnumerable)!;
- #endregion
-
- #region snippet1
- public static void Main(string[] args)
- {
- IEnumerable? suits = Suits();
- IEnumerable? ranks = Ranks();
-
- if ((suits is null) || (ranks is null))
- return;
-
- var startingDeck = (from s in suits.LogQuery("Suit Generation")
- from r in ranks.LogQuery("Value Generation")
- select new { Suit = s, Rank = r })
- .LogQuery("Starting Deck")
- .ToArray();
-
- foreach (var c in startingDeck)
- {
- Console.WriteLine(c);
- }
-
- Console.WriteLine();
-
- var times = 0;
- var shuffle = startingDeck;
-
- do
- {
- /*
- shuffle = shuffle.Take(26)
- .LogQuery("Top Half")
- .InterleaveSequenceWith(shuffle.Skip(26).LogQuery("Bottom Half"))
- .LogQuery("Shuffle")
- .ToArray();
- */
-
- shuffle = shuffle.Skip(26)
- .LogQuery("Bottom Half")
- .InterleaveSequenceWith(shuffle.Take(26).LogQuery("Top Half"))
- .LogQuery("Shuffle")
- .ToArray();
-
- foreach (var c in shuffle)
- {
- Console.WriteLine(c);
- }
-
- times++;
- Console.WriteLine(times);
- } while (!startingDeck.SequenceEquals(shuffle));
-
- Console.WriteLine(times);
- }
- #endregion
- }
-}
diff --git a/samples/snippets/csharp/getting-started/console-linq/playingcard.cs b/samples/snippets/csharp/getting-started/console-linq/playingcard.cs
deleted file mode 100644
index 033c0259ac39b..0000000000000
--- a/samples/snippets/csharp/getting-started/console-linq/playingcard.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace LinqFaroShuffle
-{
- #region snippet1
- public class PlayingCard
- {
- public Suit CardSuit { get; }
- public Rank CardRank { get; }
-
- public PlayingCard(Suit s, Rank r)
- {
- CardSuit = s;
- CardRank = r;
- }
-
- public override string ToString()
- {
- return $"{CardRank} of {CardSuit}";
- }
- }
- #endregion
-}
\ No newline at end of file