From 6ced6832ea30b6e20b5bae4ba3b4e71c6cedcda1 Mon Sep 17 00:00:00 2001 From: Randolph West Date: Fri, 25 May 2018 05:40:05 -0600 Subject: [PATCH 1/5] Case-sensitive issue in Dockerfile (#5594) On macOS and other operating systems with case-sensitive file systems, the docker command will not find the WeatherMicroService.cs file. Also corrected the output DLL. --- docs/csharp/tutorials/microservices.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/csharp/tutorials/microservices.md b/docs/csharp/tutorials/microservices.md index 60707ba41e1cd..13fdde519b14b 100644 --- a/docs/csharp/tutorials/microservices.md +++ b/docs/csharp/tutorials/microservices.md @@ -327,7 +327,7 @@ WORKDIR /app # copy csproj and restore as distinct layers -COPY WeatherMicroservice.csproj . +COPY WeatherMicroService.csproj . RUN dotnet restore # copy and build everything else @@ -348,7 +348,7 @@ publish command builds and packages your application. The final line of the file runs the application: ``` -ENTRYPOINT ["dotnet", "out/WeatherMicroservice.dll", "--server.urls", "http://0.0.0.0:5000"] +ENTRYPOINT ["dotnet", "out/WeatherMicroService.dll", "--server.urls", "http://0.0.0.0:5000"] ``` This configured port is referenced in the `--server.urls` From 95675e475b0a38c40ddab66d5ec66b9bd1d537ae Mon Sep 17 00:00:00 2001 From: Petr Kulikov <15279990+pkulikov@users.noreply.github.com> Date: Fri, 25 May 2018 15:59:59 +0200 Subject: [PATCH 2/5] Updated the foreach keyword topic; removed outdated how-to (#5597) * Updated foreach keyword topic and deleted outdated content * Fixed warning * More clarifications --- .openpublishing.redirection.json | 4 + docs/csharp/how-to/index.md | 3 +- .../compiler-messages/cs1579.md | 40 ++++----- .../codesnippet/CSharp/foreach-in_1.cs | 73 ----------------- .../language-reference/keywords/foreach-in.md | 58 +++++-------- .../keywords/iteration-statements.md | 37 ++++----- docs/csharp/misc/cs0278.md | 6 +- .../arrays/using-foreach-with-arrays.md | 37 +++++---- ...ccess-a-collection-class-with-foreach_1.cs | 7 -- ...ccess-a-collection-class-with-foreach_2.cs | 82 ------------------- ...-access-a-collection-class-with-foreach.md | 63 -------------- .../classes-and-structs/toc.md | 1 - .../programming-guide/concepts/collections.md | 3 +- docs/csharp/quick-starts/hello-world.yml | 2 +- 14 files changed, 80 insertions(+), 336 deletions(-) delete mode 100644 docs/csharp/language-reference/keywords/codesnippet/CSharp/foreach-in_1.cs delete mode 100644 docs/csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_1.cs delete mode 100644 docs/csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_2.cs delete mode 100644 docs/csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index aa212c8ede7b7..a45768a587f55 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -1297,6 +1297,10 @@ { "source_path":"docs/csharp/language-reference/operators/null-conditional-operator.md", "redirect_url":"/dotnet/csharp/language-reference/operators/null-coalescing-operator" + }, + { + "source_path":"docs/csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md", + "redirect_url":"/dotnet/csharp/language-reference/keywords/foreach-in" } ] } diff --git a/docs/csharp/how-to/index.md b/docs/csharp/how-to/index.md index 24f1a09d1fa26..a07a5761e325c 100644 --- a/docs/csharp/how-to/index.md +++ b/docs/csharp/how-to/index.md @@ -42,9 +42,8 @@ You create classes and structs to implement your program. These techniques are c These articles help you work with collections of data. - [Initialize a dictionary with a collection initializer](../programming-guide/classes-and-structs/how-to-initialize-a-dictionary-with-a-collection-initializer.md). -- [Access all the elements in a collection using `foreach`](../programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md). -## strings +## Working with strings Strings are the fundamental data type used to display or manipulate text. These articles demonstrate common practices with strings. diff --git a/docs/csharp/language-reference/compiler-messages/cs1579.md b/docs/csharp/language-reference/compiler-messages/cs1579.md index 5995371b1f198..64e0d8c9cc9b2 100644 --- a/docs/csharp/language-reference/compiler-messages/cs1579.md +++ b/docs/csharp/language-reference/compiler-messages/cs1579.md @@ -1,6 +1,6 @@ --- title: "Compiler Error CS1579" -ms.date: 07/20/2015 +ms.date: 05/24/2018 f1_keywords: - "CS1579" helpviewer_keywords: @@ -8,23 +8,17 @@ helpviewer_keywords: ms.assetid: 1eba84ce-58df-4fe3-9134-e26efefdc4ab --- # Compiler Error CS1579 -foreach statement cannot operate on variables of type 'type1' because 'type2' does not contain a public definition for 'identifier' - - To iterate through a collection using the [foreach](../../../csharp/language-reference/keywords/foreach-in.md) statement, the collection must meet the following requirements: - -- It must be an interface, class or struct. - -- It must include a public method that returns a type. - -- The return type must contain a public property named , and a public method named . - -- For more information, see [How to: Access a Collection Class with foreach](../../../csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md). - -## Example - In this sample, [foreach](../../../csharp/language-reference/keywords/foreach-in.md) is not able to iterate through the collection because there is no `public` method in `MyCollection`. - - The following sample generates CS1579. - +foreach statement cannot operate on variables of type 'type1' because 'type2' does not contain a public definition for 'identifier' + +To iterate through a collection using the [foreach](../keywords/foreach-in.md) statement, the collection must meet the following requirements: + +- Its type must include a public parameterless `GetEnumerator` method whose return type is either class, struct, or interface type. +- The return type of the `GetEnumerator` method must contain a public property named `Current` and a public parameterless method named `MoveNext` whose return type is . + +## Example + +The following sample generates CS1579 because the `MyCollection` class doesn't contain the public `GetEnumerator` method: + ```csharp // CS1579.cs using System; @@ -59,16 +53,10 @@ public class MyCollection public bool MoveNext() { nIndex++; - return(nIndex < collection.items.GetLength(0)); + return (nIndex < collection.items.Length); } - public int Current - { - get - { - return(collection.items[nIndex]); - } - } + public int Current => collection.items[nIndex]; } public static void Main() diff --git a/docs/csharp/language-reference/keywords/codesnippet/CSharp/foreach-in_1.cs b/docs/csharp/language-reference/keywords/codesnippet/CSharp/foreach-in_1.cs deleted file mode 100644 index f69d9ebc579fc..0000000000000 --- a/docs/csharp/language-reference/keywords/codesnippet/CSharp/foreach-in_1.cs +++ /dev/null @@ -1,73 +0,0 @@ -class ForEachTest -{ - static void Main(string[] args) - { - ExampleOne(); - ExampleTwo(); - ExampleThree(); - } - - private static void ExampleOne() // 12 - 26 - { - int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 }; - foreach (int element in fibarray) - { - System.Console.WriteLine(element); - } - System.Console.WriteLine(); - // Output: - // 0 - // 1 - // 1 - // 2 - // 3 - // 5 - // 8 - // 13 - } - - private static void ExampleTwo() // 31-46 - { - int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 }; - // Compare the previous loop to a similar for loop. - for (int i = 0; i < fibarray.Length; i++) - { - System.Console.WriteLine(fibarray[i]); - } - System.Console.WriteLine(); - // Output: - // 0 - // 1 - // 1 - // 2 - // 3 - // 5 - // 8 - // 13 - } - - private static void ExampleThree() // 51 - 69 - { - int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 }; - // You can maintain a count of the elements in the collection. - int count = 0; - foreach (int element in fibarray) - { - count += 1; - System.Console.WriteLine("Element #{0}: {1}", count, element); - } - System.Console.WriteLine("Number of elements in the array: {0}", count); - // Output: - // Element #1: 0 - // Element #2: 1 - // Element #3: 1 - // Element #4: 2 - // Element #5: 3 - // Element #6: 5 - // Element #7: 8 - // Element #8: 13 - // Number of elements in the array: 8 - } - - -} \ No newline at end of file diff --git a/docs/csharp/language-reference/keywords/foreach-in.md b/docs/csharp/language-reference/keywords/foreach-in.md index 74c52c293816a..1de46a6fa6867 100644 --- a/docs/csharp/language-reference/keywords/foreach-in.md +++ b/docs/csharp/language-reference/keywords/foreach-in.md @@ -1,6 +1,6 @@ --- title: "foreach, in (C# Reference)" -ms.date: 10/11/2017 +ms.date: 05/24/2018 f1_keywords: - "foreach" - "foreach_CSharpKeyword" @@ -12,55 +12,35 @@ ms.assetid: 5a9c5ddc-5fd3-457a-9bb6-9abffcd874ec --- # foreach, in (C# Reference) -The `foreach` statement repeats a group of embedded statements for each element in an array or an object collection that implements the or interface. The [foreach statement](/dotnet/csharp/language-reference/language-specification/statements#the-foreach-statement) is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a [for](for.md) loop. - - The embedded statements continue to execute for each element in the array or collection. After the iteration has been completed for all the elements in the collection, control is transferred to the next statement following the `foreach` block. - - At any point within the `foreach` block, you can break out of the loop by using the [break](break.md) keyword, or step to the next iteration in the loop by using the [continue](continue.md) keyword. +The `foreach` statement executes a statement or a block of statements for each element in an instance of the type that implements the or interface. The `foreach` statement is not limited to those types and can be applied to an instance of any type that satisfies the following conditions: - A `foreach` loop can also be exited by the [goto](goto.md), [return](return.md), or [throw](throw.md) statements. +- has the public parameterless `GetEnumerator` method whose return type is either class, struct, or interface type, +- the return type of the `GetEnumerator` method has the public `Current` property and the public parameterless `MoveNext` method whose return type is . - For more information about the `foreach` keyword and code samples, see the following topics: +At any point within the `foreach` statement block, you can break out of the loop by using the [break](break.md) keyword, or step to the next iteration in the loop by using the [continue](continue.md) keyword. You also can exit a `foreach` loop by the [goto](goto.md), [return](return.md), or [throw](throw.md) statements. - [Using foreach with Arrays](../../programming-guide/arrays/using-foreach-with-arrays.md) +## Examples - [How to: Access a Collection Class with foreach](../../programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md) +[!INCLUDE[interactive-note](~/includes/csharp-interactive-note.md)] -## Example +The following example shows usage of the `foreach` statement with an instance of the type that implements the interface: -The following code shows three examples: +[!code-csharp-interactive[list example](~/samples/snippets/csharp/keywords/IterationKeywordsExamples.cs#1)] -> [!TIP] -> You can modify the examples to experiment with the syntax and try different -> usages that are more similar to your use case. Press "Run" to run the code, -> then edit and press "Run" again. +The next example uses the `foreach` statement with an instance of the type, which doesn't implement any interfaces: -- a typical `foreach` loop that displays the contents of an array of integers +[!code-csharp-interactive[span example](~/samples/snippets/csharp/keywords/IterationKeywordsExamples.cs#2)] -[!code-csharp-interactive[csrefKeywordsIteration#4](./codesnippet/CSharp/foreach-in_1.cs#L12-L26)] - -- a [for](../../../csharp/language-reference/keywords/for.md) loop that does the same thing - -[!code-csharp-interactive[csrefKeywordsIteration#4](./codesnippet/CSharp/foreach-in_1.cs#L31-L46)] - -- a `foreach` loop that maintains a count of the number of elements in the array - -[!code-csharp-interactive[csrefKeywordsIteration#4](./codesnippet/CSharp/foreach-in_1.cs#L51-L69)] - ## C# Language Specification [!INCLUDE[CSharplangspec](~/includes/csharplangspec-md.md)] -## See Also - -[The foreach statement (C# language specification)](/dotnet/csharp/language-reference/language-specification/statements#the-foreach-statement) - -[C# Reference](../index.md) - -[C# Programming Guide](../../programming-guide/index.md) - -[C# Keywords](index.md) - -[Iteration Statements](iteration-statements.md) +## See also -[for](for.md) +[The foreach statement (C# language specification)](/dotnet/csharp/language-reference/language-specification/statements#the-foreach-statement) +[Using foreach with Arrays](../../programming-guide/arrays/using-foreach-with-arrays.md) +[for](for.md) +[Iteration Statements](iteration-statements.md) +[C# Keywords](index.md) +[C# Reference](../index.md) +[C# Programming Guide](../../programming-guide/index.md) \ No newline at end of file diff --git a/docs/csharp/language-reference/keywords/iteration-statements.md b/docs/csharp/language-reference/keywords/iteration-statements.md index 7bd87f4ec5f8e..ba4adc5aa8025 100644 --- a/docs/csharp/language-reference/keywords/iteration-statements.md +++ b/docs/csharp/language-reference/keywords/iteration-statements.md @@ -7,22 +7,21 @@ helpviewer_keywords: ms.assetid: 7d494566-bf75-4ee8-979f-0f964209437e --- # Iteration Statements (C# Reference) -You can create loops by using the iteration statements. Iteration statements cause embedded statements to be executed a number of times, subject to the loop-termination criteria. These statements are executed in order, except when a [jump statement](../../../csharp/language-reference/keywords/jump-statements.md) is encountered. - - The following keywords are used in iteration statements: - -- [do](../../../csharp/language-reference/keywords/do.md) - -- [for](../../../csharp/language-reference/keywords/for.md) - -- [foreach](../../../csharp/language-reference/keywords/foreach-in.md) - -- [in](../../../csharp/language-reference/keywords/foreach-in.md) - -- [while](../../../csharp/language-reference/keywords/while.md) - -## See Also - [C# Reference](../../../csharp/language-reference/index.md) - [C# Programming Guide](../../../csharp/programming-guide/index.md) - [C# Keywords](../../../csharp/language-reference/keywords/index.md) - [Statement Keywords](../../../csharp/language-reference/keywords/statement-keywords.md) + +You can create loops by using the iteration statements. Iteration statements cause embedded statements to be executed a number of times, subject to the loop-termination criteria. These statements are executed in order, except when a [jump statement](../../../csharp/language-reference/keywords/jump-statements.md) is encountered. + +The following keywords are used in iteration statements: + +- [do](do.md) + +- [for](for.md) + +- [foreach, in](foreach-in.md) + +- [while](while.md) + +## See also + [C# Reference](../index.md) + [C# Programming Guide](../../programming-guide/index.md) + [C# Keywords](index.md) + [Statement Keywords](statement-keywords.md) diff --git a/docs/csharp/misc/cs0278.md b/docs/csharp/misc/cs0278.md index b763ca6cdb762..01f01d1f1588f 100644 --- a/docs/csharp/misc/cs0278.md +++ b/docs/csharp/misc/cs0278.md @@ -10,11 +10,9 @@ ms.assetid: 5418cbbe-bcec-4379-a6f6-410987beb96a # Compiler Warning (level 2) CS0278 'type' does not implement the 'pattern name' pattern. 'method name' is ambiguous with 'method name'. - There are several statements in C# that rely on defined patterns, such as `foreach` and `using`. For example, `foreach` relies on the collection class implementing the "enumerable" pattern. +There are several statements in C# that rely on defined patterns, such as `foreach` and `using`. For example, the [`foreach` statement](../language-reference/keywords/foreach-in.md) relies on the collection class implementing the "enumerable" pattern. - CS0278 can occur if the compiler is unable to make the match due to ambiguities. For example, the "enumerable" pattern requires that there be a method called `MoveNext`, and your code might contain two methods called `MoveNext`. The compiler will attempt to find an interface to use, but it is recommended that you determine and resolve the cause of the ambiguity. - - For more information, see [How to: Access a Collection Class with foreach](../../csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md). +CS0278 can occur if the compiler is unable to make the match due to ambiguities. For example, the "enumerable" pattern requires that there be a method called `MoveNext`, and your code might contain two methods called `MoveNext`. The compiler will attempt to find an interface to use, but it is recommended that you determine and resolve the cause of the ambiguity. ## Example The following sample generates CS0278. diff --git a/docs/csharp/programming-guide/arrays/using-foreach-with-arrays.md b/docs/csharp/programming-guide/arrays/using-foreach-with-arrays.md index 3f6c4f93a250d..8b772307ae2cf 100644 --- a/docs/csharp/programming-guide/arrays/using-foreach-with-arrays.md +++ b/docs/csharp/programming-guide/arrays/using-foreach-with-arrays.md @@ -1,26 +1,29 @@ --- title: "Using foreach with Arrays (C# Programming Guide)" -ms.date: 07/20/2015 +ms.date: 05/23/2018 helpviewer_keywords: - "arrays [C#], foreach" - "foreach statement [C#], using with arrays" ms.assetid: 5f2da2a9-1f56-4de5-94cc-e07f4f7a0244 --- # Using foreach with Arrays (C# Programming Guide) -C# also provides the [foreach](../../../csharp/language-reference/keywords/foreach-in.md) statement. This statement provides a simple, clean way to iterate through the elements of an array or any enumerable collection. The `foreach` statement processes elements in the order returned by the array or collection type’s enumerator, which is usually from the 0th element to the last. For example, the following code creates an array called `numbers` and iterates through it with the `foreach` statement: - - [!code-csharp[csProgGuideArrays#28](../../../csharp/programming-guide/arrays/codesnippet/CSharp/using-foreach-with-arrays_1.cs)] - - With multidimensional arrays, you can use the same method to iterate through the elements, for example: - - [!code-csharp[csProgGuideArrays#29](../../../csharp/programming-guide/arrays/codesnippet/CSharp/using-foreach-with-arrays_2.cs)] - - However, with multidimensional arrays, using a nested [for](../../../csharp/language-reference/keywords/for.md) loop gives you more control over the array elements. - -## See Also + +The [foreach](../../language-reference/keywords/foreach-in.md) statement provides a simple, clean way to iterate through the elements of an array. + +For single-dimensional arrays, the `foreach` statement processes elements in increasing index order, starting with index 0 and ending with index `Length - 1`: + +[!code-csharp[csProgGuideArrays#28](./codesnippet/CSharp/using-foreach-with-arrays_1.cs)] + +For multi-dimensional arrays, elements are traversed such that the indices of the rightmost dimension are increased first, then the next left dimension, and so on to the left: + +[!code-csharp[csProgGuideArrays#29](./codesnippet/CSharp/using-foreach-with-arrays_2.cs)] + +However, with multidimensional arrays, using a nested [for](../../language-reference/keywords/for.md) loop gives you more control over the order in which to process the array elements. + +## See also - [C# Programming Guide](../../../csharp/programming-guide/index.md) - [Arrays](../../../csharp/programming-guide/arrays/index.md) - [Single-Dimensional Arrays](../../../csharp/programming-guide/arrays/single-dimensional-arrays.md) - [Multidimensional Arrays](../../../csharp/programming-guide/arrays/multidimensional-arrays.md) - [Jagged Arrays](../../../csharp/programming-guide/arrays/jagged-arrays.md) + [C# Programming Guide](../index.md) + [Arrays](index.md) + [Single-Dimensional Arrays](single-dimensional-arrays.md) + [Multidimensional Arrays](multidimensional-arrays.md) + [Jagged Arrays](jagged-arrays.md) diff --git a/docs/csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_1.cs b/docs/csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_1.cs deleted file mode 100644 index 77cdc132cf1ba..0000000000000 --- a/docs/csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_1.cs +++ /dev/null @@ -1,7 +0,0 @@ - Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'}); - - // Display the tokens. - foreach (string item in f) - { - System.Console.WriteLine(item); - } \ No newline at end of file diff --git a/docs/csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_2.cs b/docs/csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_2.cs deleted file mode 100644 index 9dde16cce96ae..0000000000000 --- a/docs/csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_2.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Collections; - -// Declare the Tokens class. The class implements the IEnumerable interface. -public class Tokens : IEnumerable -{ - private string[] elements; - - Tokens(string source, char[] delimiters) - { - // The constructor parses the string argument into tokens. - elements = source.Split(delimiters); - } - - // The IEnumerable interface requires implementation of method GetEnumerator. - public IEnumerator GetEnumerator() - { - return new TokenEnumerator(this); - } - - - // Declare an inner class that implements the IEnumerator interface. - private class TokenEnumerator : IEnumerator - { - private int position = -1; - private Tokens t; - - public TokenEnumerator(Tokens t) - { - this.t = t; - } - - // The IEnumerator interface requires a MoveNext method. - public bool MoveNext() - { - if (position < t.elements.Length - 1) - { - position++; - return true; - } - else - { - return false; - } - } - - // The IEnumerator interface requires a Reset method. - public void Reset() - { - position = -1; - } - - // The IEnumerator interface requires a Current method. - public object Current - { - get - { - return t.elements[position]; - } - } - } - - - // Test the Tokens class. - static void Main() - { - // Create a Tokens instance. - Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'}); - - // Display the tokens. - foreach (string item in f) - { - System.Console.WriteLine(item); - } - } -} -/* Output: - This - is - a - sample - sentence. -*/ \ No newline at end of file diff --git a/docs/csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md b/docs/csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md deleted file mode 100644 index 529f71a52012f..0000000000000 --- a/docs/csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "How to: Access a Collection Class with foreach (C# Programming Guide)" -ms.date: 07/20/2015 -helpviewer_keywords: - - "collection classes [C#], foreach statement" -ms.assetid: a6b9cf5c-6c8d-4223-b12c-288949434493 ---- -# How to: Access a Collection Class with foreach (C# Programming Guide) -The following code example illustrates how to write a non-generic collection class that can be used with [foreach](../../../csharp/language-reference/keywords/foreach-in.md). The example defines a string tokenizer class. - -> [!NOTE] -> This example represents recommended practice only when you cannot use a generic collection class. For an example of how to implement a type-safe generic collection class that supports , see [Iterators](http://msdn.microsoft.com/library/f45331db-d595-46ec-9142-551d3d1eb1a7). - - In the example, the following code segment uses the `Tokens` class to break the sentence "This is a sample sentence." into tokens by using ' ' and '-' as separators. The code then displays those tokens by using a `foreach` statement. - - [!code-csharp[csProgGuideCollections#3](../../../csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_1.cs)] - -## Example - Internally, the `Tokens` class uses an array to store the tokens. Because arrays implement and , the code example could have used the array's enumeration methods (, , , and ) instead of defining them in the `Tokens` class. The method definitions are included in the example to clarify how they are defined and what each does. - - [!code-csharp[csProgGuideCollections#2](../../../csharp/programming-guide/classes-and-structs/codesnippet/CSharp/how-to-access-a-collection-class-with-foreach_2.cs)] - - In C#, it is not necessary for a collection class to implement and to be compatible with `foreach`. If the class has the required , , , and members, it will work with `foreach`. Omitting the interfaces has the advantage of enabling you to define a return type for `Current` that is more specific than . This provides type safety. - - For example, change the following lines in the previous example. - -```csharp -// Change the Tokens class so that it no longer implements IEnumerable. -public class Tokens -{ - // . . . - - // Change the return type for the GetEnumerator method. - public TokenEnumerator GetEnumerator() - { } - - // Change TokenEnumerator so that it no longer implements IEnumerator. - public class TokenEnumerator - { - // . . . - - // Change the return type of method Current to string. - public string Current - { } - } - } -``` - - Because `Current` returns a string, the compiler can detect when an incompatible type is used in a `foreach` statement, as shown in the following code. - -```csharp -// Error: Cannot convert type string to int. -foreach (int item in f) -``` - - The disadvantage of omitting and is that the collection class is no longer interoperable with the `foreach` statements, or equivalent statements, of other common language runtime languages. - -## See Also - - [C# Reference](../../../csharp/language-reference/index.md) - [C# Programming Guide](../../../csharp/programming-guide/index.md) - [Arrays](../../../csharp/programming-guide/arrays/index.md) - [Collections](http://msdn.microsoft.com/library/e76533a9-5033-4a0b-b003-9c2be60d185b) diff --git a/docs/csharp/programming-guide/classes-and-structs/toc.md b/docs/csharp/programming-guide/classes-and-structs/toc.md index 4202b6adf745c..867f42b3038e9 100644 --- a/docs/csharp/programming-guide/classes-and-structs/toc.md +++ b/docs/csharp/programming-guide/classes-and-structs/toc.md @@ -47,7 +47,6 @@ ## [Object and Collection Initializers](object-and-collection-initializers.md) ### [How to: Initialize Objects by Using an Object Initializer](how-to-initialize-objects-by-using-an-object-initializer.md) ### [How to: Initialize a Dictionary with a Collection Initializer](how-to-initialize-a-dictionary-with-a-collection-initializer.md) -## [How to: Access a Collection Class with foreach](how-to-access-a-collection-class-with-foreach.md) ## [Nested Types](nested-types.md) ## [Partial Classes and Methods](partial-classes-and-methods.md) ## [Anonymous Types](anonymous-types.md) diff --git a/docs/csharp/programming-guide/concepts/collections.md b/docs/csharp/programming-guide/concepts/collections.md index b52f96b5c6fa3..afbc4f9b04a76 100644 --- a/docs/csharp/programming-guide/concepts/collections.md +++ b/docs/csharp/programming-guide/concepts/collections.md @@ -455,7 +455,7 @@ public class Car : IComparable ## Defining a Custom Collection - You can define a collection by implementing the or interface. For additional information, see [How to: Access a Collection Class with foreach](../../../csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md). + You can define a collection by implementing the or interface. Although you can define a custom collection, it is usually better to instead use the collections that are included in the .NET Framework, which are described in [Kinds of Collections](#BKMK_KindsOfCollections) earlier in this topic. @@ -580,4 +580,3 @@ private static IEnumerable EvenSequence( [Selecting a Collection Class](../../../standard/collections/selecting-a-collection-class.md) [Comparisons and Sorts Within Collections](../../../standard/collections/comparisons-and-sorts-within-collections.md) [When to Use Generic Collections](../../../standard/collections/when-to-use-generic-collections.md) - [How to: Access a Collection Class with foreach](../../../csharp/programming-guide/classes-and-structs/how-to-access-a-collection-class-with-foreach.md) diff --git a/docs/csharp/quick-starts/hello-world.yml b/docs/csharp/quick-starts/hello-world.yml index 3199fd683b9a5..28e2dca23a7d2 100644 --- a/docs/csharp/quick-starts/hello-world.yml +++ b/docs/csharp/quick-starts/hello-world.yml @@ -220,4 +220,4 @@ items: You can learn more about working with the `string` type in the [C# Programming Guide](../programming-guide/index.md) topic on [strings](../programming-guide/strings/index.md). - [How to tips on strings](../how-to/index.md#strings). + [How to tips on working with strings](../how-to/index.md#working-with-strings). From 817086fd9a7fe4ea4b3aada12096788fa761458c Mon Sep 17 00:00:00 2001 From: Ron Petrusha Date: Fri, 25 May 2018 09:10:59 -0700 Subject: [PATCH 3/5] Moved app compat item (#5590) * Moved app compat item * Modified 4.7.2 runtime compat topics --- docs/framework/migration-guide/runtime/4.0-4.7.2.md | 6 ++---- docs/framework/migration-guide/runtime/4.5-4.7.2.md | 4 ++-- docs/framework/migration-guide/runtime/4.5.1-4.7.2.md | 4 ++-- docs/framework/migration-guide/runtime/4.5.2-4.7.2.md | 4 ++-- docs/framework/migration-guide/runtime/4.6-4.7.2.md | 4 ++-- docs/framework/migration-guide/runtime/4.6.1-4.7.2.md | 4 ++-- docs/framework/migration-guide/runtime/4.6.2-4.7.2.md | 4 ++-- docs/framework/migration-guide/runtime/4.7-4.7.2.md | 4 ++-- docs/framework/migration-guide/runtime/4.7.1-4.7.2.md | 4 ++-- ...peattributedisableregex-app-setting-on-by-default-net.md | 0 10 files changed, 18 insertions(+), 20 deletions(-) rename includes/migration-guide/runtime/{web application => web}/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md (100%) diff --git a/docs/framework/migration-guide/runtime/4.0-4.7.2.md b/docs/framework/migration-guide/runtime/4.0-4.7.2.md index d3e3094d7cadc..db2ba278c1eb1 100644 --- a/docs/framework/migration-guide/runtime/4.0-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.0-4.7.2.md @@ -166,12 +166,10 @@ If you are migrating from the .NET Framework 4.0 to 4.7.2, review the following [!include[Contract.Invariant or Contract.Requires do not consider String.IsNullOrEmpty to be pure](~/includes/migration-guide/runtime/tools/contractinvariant-contractrequirestexception-do-not-consider.md)] -## Web Application - -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] - ## Web Applications +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] + [!include[Managed browser hosting controls from the .NET Framework 1.1 and 2.0 are blocked](~/includes/migration-guide/runtime/web/managed-browser-hosting-controls-from-net-framework-11-20-are-blocked.md)] ## Windows Communication Foundation (WCF) diff --git a/docs/framework/migration-guide/runtime/4.5-4.7.2.md b/docs/framework/migration-guide/runtime/4.5-4.7.2.md index b9d3ab10990f8..9148d2bf2d5eb 100644 --- a/docs/framework/migration-guide/runtime/4.5-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.5-4.7.2.md @@ -114,9 +114,9 @@ If you are migrating from the .NET Framework 4.5 to 4.7.2, review the following [!include[Contract.Invariant or Contract.Requires do not consider String.IsNullOrEmpty to be pure](~/includes/migration-guide/runtime/tools/contractinvariant-contractrequirestexception-do-not-consider.md)] -## Web Application +## Web Applications -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] ## Windows Communication Foundation (WCF) diff --git a/docs/framework/migration-guide/runtime/4.5.1-4.7.2.md b/docs/framework/migration-guide/runtime/4.5.1-4.7.2.md index 4313df4add4df..b26b4bc8440eb 100644 --- a/docs/framework/migration-guide/runtime/4.5.1-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.5.1-4.7.2.md @@ -96,9 +96,9 @@ If you are migrating from the .NET Framework 4.5.1 to 4.7.2, review the followin [!include[Contract.Invariant or Contract.Requires do not consider String.IsNullOrEmpty to be pure](~/includes/migration-guide/runtime/tools/contractinvariant-contractrequirestexception-do-not-consider.md)] -## Web Application +## Web Applications -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] ## Windows Communication Foundation (WCF) diff --git a/docs/framework/migration-guide/runtime/4.5.2-4.7.2.md b/docs/framework/migration-guide/runtime/4.5.2-4.7.2.md index 5914a7423b3d3..43cc921bb9f67 100644 --- a/docs/framework/migration-guide/runtime/4.5.2-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.5.2-4.7.2.md @@ -82,9 +82,9 @@ If you are migrating from the .NET Framework 4.5.2 to 4.7.2, review the followin [!include[Contract.Invariant or Contract.Requires do not consider String.IsNullOrEmpty to be pure](~/includes/migration-guide/runtime/tools/contractinvariant-contractrequirestexception-do-not-consider.md)] -## Web Application +## Web Applications -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] ## Windows Communication Foundation (WCF) diff --git a/docs/framework/migration-guide/runtime/4.6-4.7.2.md b/docs/framework/migration-guide/runtime/4.6-4.7.2.md index f88d1d1b84e4c..bc94d9939dc05 100644 --- a/docs/framework/migration-guide/runtime/4.6-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.6-4.7.2.md @@ -44,9 +44,9 @@ If you are migrating from the .NET Framework 4.6 to 4.7.2, review the following [!include[Contract.Invariant or Contract.Requires do not consider String.IsNullOrEmpty to be pure](~/includes/migration-guide/runtime/tools/contractinvariant-contractrequirestexception-do-not-consider.md)] -## Web Application +## Web Applications -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] ## Windows Communication Foundation (WCF) diff --git a/docs/framework/migration-guide/runtime/4.6.1-4.7.2.md b/docs/framework/migration-guide/runtime/4.6.1-4.7.2.md index f54f800b29416..84704cddda54a 100644 --- a/docs/framework/migration-guide/runtime/4.6.1-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.6.1-4.7.2.md @@ -40,9 +40,9 @@ If you are migrating from the .NET Framework 4.6.1 to 4.7.2, review the followin [!include[SignedXml and EncryptedXml Breaking Changes](~/includes/migration-guide/runtime/security/signedxml-encryptedxml-breaking-changes.md)] -## Web Application +## Web Applications -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] ## Windows Communication Foundation (WCF) diff --git a/docs/framework/migration-guide/runtime/4.6.2-4.7.2.md b/docs/framework/migration-guide/runtime/4.6.2-4.7.2.md index 8f355a11c4f37..830bf7f8ad7e3 100644 --- a/docs/framework/migration-guide/runtime/4.6.2-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.6.2-4.7.2.md @@ -28,9 +28,9 @@ If you are migrating from the .NET Framework 4.6.2 to 4.7.2, review the followin [!include[RSACng and DSACng are once again usable in Partial Trust scenarios](~/includes/migration-guide/runtime/security/rsacng-dsacng-are-once-again-usable-partial-trust-scenarios.md)] -## Web Application +## Web Applications -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] ## Windows Communication Foundation (WCF) diff --git a/docs/framework/migration-guide/runtime/4.7-4.7.2.md b/docs/framework/migration-guide/runtime/4.7-4.7.2.md index 3ed3678802323..9291ddfa288b6 100644 --- a/docs/framework/migration-guide/runtime/4.7-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.7-4.7.2.md @@ -32,9 +32,9 @@ If you are migrating from the .NET Framework 4.7 to 4.7.2, review the following [!include[RSACng and DSACng are once again usable in Partial Trust scenarios](~/includes/migration-guide/runtime/security/rsacng-dsacng-are-once-again-usable-partial-trust-scenarios.md)] -## Web Application +## Web Applications -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] ## Windows Communication Foundation (WCF) diff --git a/docs/framework/migration-guide/runtime/4.7.1-4.7.2.md b/docs/framework/migration-guide/runtime/4.7.1-4.7.2.md index 206a65f5a6c94..ca823729b912c 100644 --- a/docs/framework/migration-guide/runtime/4.7.1-4.7.2.md +++ b/docs/framework/migration-guide/runtime/4.7.1-4.7.2.md @@ -24,9 +24,9 @@ If you are migrating from the .NET Framework 4.7.1 to 4.7.2, review the followin [!include[Improved WCF chain trust certificate validation for Net.Tcp certificate authentication](~/includes/migration-guide/runtime/runtime/improved-wcf-chain-trust-certificate-validation-for-nettcp-authentication.md)] -## Web Application +## Web Applications -[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] +[!include["dataAnnotations:dataTypeAttribute:disableRegEx" app setting is on by default in .NET Framework 4.7.2](~/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md)] ## Windows Presentation Foundation (WPF) diff --git a/includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md b/includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md similarity index 100% rename from includes/migration-guide/runtime/web application/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md rename to includes/migration-guide/runtime/web/dataannotationsdatatypeattributedisableregex-app-setting-on-by-default-net.md From a90328a576736e433ad6cd2f75443bf97e1b1f4d Mon Sep 17 00:00:00 2001 From: Phillip Carter Date: Fri, 25 May 2018 11:14:34 -0700 Subject: [PATCH 4/5] Update records as per feedback (#5610) --- docs/fsharp/language-reference/records.md | 34 ++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/docs/fsharp/language-reference/records.md b/docs/fsharp/language-reference/records.md index 0ba3eb5db7aed..40387ab6c5476 100644 --- a/docs/fsharp/language-reference/records.md +++ b/docs/fsharp/language-reference/records.md @@ -11,15 +11,15 @@ Records represent simple aggregates of named values, optionally with members. S ```fsharp [ attributes ] -type [accessibility-modifier] typename = { - [ mutable ] label1 : type1; - [ mutable ] label2 : type2; - ... -} - [ member-list ] +type [accessibility-modifier] typename = + { [ mutable ] label1 : type1; + [ mutable ] label2 : type2; + ... } + [ member-list ] ``` ## Remarks + In the previous syntax, *typename* is the name of the record type, *label1* and *label2* are names of values, referred to as *labels*, and *type1* and *type2* are the types of these values. *member-list* is the optional list of members for the type. You can use the `[]` attribute to create a struct record rather than a record which is a reference type. Following are some examples. @@ -43,6 +43,7 @@ The labels of the most recently declared type take precedence over those of the Methods can be defined for record types just as for class types. ## Creating Records by Using Record Expressions + You can initialize records by using the labels that are defined in the record. An expression that does this is referred to as a *record expression*. Use braces to enclose the record expression and use the semicolon as a delimiter. The following example shows how to create a record. @@ -72,20 +73,19 @@ Don't use the DefaultValue attribute with record fields. A better approach is to ```fsharp // Rather than use [], define a default record. type MyRecord = -{ - field1 : int - field2 : int -} + { Field1 : int + Field2 : int } -let defaultRecord1 = { field1 = 0; field2 = 0 } -let defaultRecord2 = { field1 = 1; field2 = 25 } +let defaultRecord1 = { Field1 = 0; Field2 = 0 } +let defaultRecord2 = { Field1 = 1; Field2 = 25 } // Use the with keyword to populate only a few chosen fields // and leave the rest with default values. -let rr3 = { defaultRecord1 with field2 = 42 } +let rr3 = { defaultRecord1 with Field2 = 42 } ``` ## Pattern Matching with Records + Records can be used with pattern matching. You can specify some fields explicitly and provide variables for other fields that will be assigned when a match occurs. The following code example illustrates this. [!code-fsharp[Main](../../../samples/snippets/fsharp/lang-ref-1/snippet1910.fs)] @@ -99,17 +99,25 @@ Point is at (10.000000, 0.000000, -1.000000). ``` ## Differences Between Records and Classes + Record fields differ from classes in that they are automatically exposed as properties, and they are used in the creation and copying of records. Record construction also differs from class construction. In a record type, you cannot define a constructor. Instead, the construction syntax described in this topic applies. Classes have no direct relationship between constructor parameters, fields, and properties. Like union and structure types, records have structural equality semantics. Classes have reference equality semantics. The following code example demonstrates this. [!code-fsharp[Main](../../../samples/snippets/fsharp/lang-ref-1/snippet1911.fs)] +The output of this code is as follows: + +``` +The records are equal. +``` + If you write the same code with classes, the two class objects would be unequal because the two values would represent two objects on the heap and only the addresses would be compared (unless the class type overrides the `System.Object.Equals` method). If you need reference equality for records, add the attribute `[]` above the record. ## See Also + [F# Types](fsharp-types.md) [Classes](classes.md) From 1aa1f3c5ca6defb79b716de540ab0abae04d41ee Mon Sep 17 00:00:00 2001 From: John Alexander Date: Fri, 25 May 2018 14:14:14 -0500 Subject: [PATCH 5/5] Update SentimentAnalysis tutorial with new datasets (#5616) * Update SentimentAnalysis tutorial with new datasets * Fixed link * Revised based on feedback --- .../tutorials/sentiment-analysis.md | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/docs/machine-learning/tutorials/sentiment-analysis.md b/docs/machine-learning/tutorials/sentiment-analysis.md index fcb6e88429ac7..e198e42a54b9b 100644 --- a/docs/machine-learning/tutorials/sentiment-analysis.md +++ b/docs/machine-learning/tutorials/sentiment-analysis.md @@ -1,13 +1,16 @@ --- title: Use ML.NET in a sentiment analysis classification scenario description: Discover how to use ML.NET in a classification scenario to understand how to use sentiment prediction to take the appropriaste action. -ms.date: 05/21/2018 +ms.date: 05/24/2018 ms.custom: mvc #Customer intent: As a developer, I want to use ML.NET to apply a binary classification task so that I can understand how to use sentiment prediction to take appropriaste action. --- -# Tutorial: Use the ML.NET APIs in a sentiment analysis classification scenario +# Tutorial: Use ML.NET in a sentiment analysis classification scenario -This sample tutorial illustrates using the ML.NET API to create a sentiment classifier via a .NET Core console application using C# in Visual Studio 2017. +> [!NOTE] +> This topic refers to ML.NET, which is currently in Preview, and material may be subject to change. For more information, visit [the ML.NET introduction](https://www.microsoft.com/net/learn/apps/machine-learning-and-ai/ml-dotnet). + +This sample tutorial illustrates using ML.NET to create a sentiment classifier via a .NET Core console application using C# in Visual Studio 2017. In this tutorial, you learn how to: > [!div class="checklist"] @@ -15,16 +18,12 @@ In this tutorial, you learn how to: > * Create the learning pipeline > * Load a classifier > * Train the model -> * Predict the model +> * Predict the test data outcomes with the model > * Evaluate the model with a different dataset ## Sentiment analysis sample overview -The sample is a console app that uses the ML.NET API to train a model that classifies and predicts sentiment as either positive or negative. It also evaluates the model with a second dataset for quality analysis. The sentiment datasets are from University of California, Irvine (UCI). - -Prediction and evaluation results are displayed accordingly so that analysis and action can be taken. - -Sentiment analysis is either positive or negative. So, you can use classification to train the model, for prediction, and for evaluation. +The sample is a console app that uses ML.NET to train a model that classifies and predicts sentiment as either positive or negative. It also evaluates the model with a second dataset for quality analysis. The sentiment datasets are from the WikiDetox project. ## Machine learning workflow @@ -52,13 +51,17 @@ You then need to **determine** the sentiment, which helps you with the machine l With this problem, you know the following facts: Training data: website comments can be positive or negative (**sentiment**). -Predict the **sentiment** of a new website comment, either positive or negative. +Predict the **sentiment** of a new website comment, either positive or negative, such as in the following examples: + +* Please refrain from adding nonsense to Wikipedia. +* He is the best, and the article should say that. ## Prerequisites * [Visual Studio 2017 15.6 or later](https://www.visualstudio.com/downloads/?utm_medium=microsoft&utm_source=docs.microsoft.com&utm_campaign=button+cta&utm_content=download+vs2017) with the ".NET Core cross-platform development" workload installed. -* [The UCI Sentiment Labeled Sentences dataset zip file](https://archive.ics.uci.edu/ml/machine-learning-databases/00331/sentiment%20labelled%20sentences.zip) +* The [Wikipedia detox line data tab separated file (wikiPedia-detox-250-line-data.tsv)](https://github.com/dotnet/machinelearning/blob/master/test/data/wikipedia-detox-250-line-data.tsv). +* The [Wikipedia detox line test tab separated file (wikipedia-detox-250-line-test.tsv)](https://github.com/dotnet/machinelearning/blob/master/test/data/wikipedia-detox-250-line-test.tsv). ## Create a console application @@ -74,15 +77,10 @@ Predict the **sentiment** of a new website comment, either positive or negative. ### Prepare your data -1. Download [The UCI Sentiment Labeled Sentences dataset zip file (see citations in the following note)](https://archive.ics.uci.edu/ml/machine-learning-databases/00331/sentiment%20labelled%20sentences.zip), unzip the file and copy the following two files into the *Data* directory you created: +1. Download the [WikiPedia detox-250-line-data.tsv](https://github.com/dotnet/machinelearning/blob/master/test/data/wikipedia-detox-250-line-data.tsv) and the [wikipedia-detox-250-line-test.tsv](https://github.com/dotnet/machinelearning/blob/master/test/data/wikipedia-detox-250-line-test.tsv) data sets and save them to the *Data* folder previously created. The first dataset trains the machine learning model and the second can be used to evaluate how accurate your model is. -* *imdb_labelled.txt* -* *yelp_labelled.txt* -> [!NOTE] -> The datasets this tutorial uses are from the 'From Group to Individual Labels using Deep Features', Kotzias et. al,. KDD 2015, and hosted at the UCI Machine Learning Repository - Dua, D. and Karra Taniskidou, E. (2017). UCI Machine Learning Repository [http://archive.ics.uci.edu/ml]. Irvine, CA: University of California, School of Information and Computer Science. - -2. In Solution Explorer, right-click each of the \*.txt files and select **Properties**. Under **Advanced**, change the value of **Copy to Output Directory** to **Always**. +2. In Solution Explorer, right-click each of the \*.tsv files and select **Properties**. Under **Advanced**, change the value of **Copy to Output Directory** to **Always**. ### Create classes and define paths @@ -113,7 +111,7 @@ Remove the existing class definition and add the following code, which has two c [!code-csharp[DeclareTypes](../../../samples/machine-learning/tutorials/SentimentAnalysis/SentimentData.cs#2 "Declare data record types")] -`SentimentData` is the input dataset class and has a string for the comment (`SentimentText`), a `float` (`Sentiment`) that has a value for sentiment of either positive or negative. Both fields have `Column` attributes attached to them. This attribute describes the order of each field in the data file, and which is the `Label` field. `SentimentPrediction` is the class used for prediction after the model has been trained. It has a single boolean (`Sentiment`) and a `PredictedLabel` `ColumnName` attribute. The `Label` is used to create and train the model, and it's also used with a second dataset to evaluate the model. The `PredictedLabel` is used during prediction and evaluation. For evaluation, an input with training data, the predicted values, and the model are used. +`SentimentData` is the input dataset class and has a `float` (`Sentiment`) that has a value for sentiment of either positive or negative, and a string for the comment (`SentimentText`). Both fields have `Column` attributes attached to them. This attribute describes the order of each field in the data file, and which is the `Label` field. `SentimentPrediction` is the class used for prediction after the model has been trained. It has a single boolean (`Sentiment`) and a `PredictedLabel` `ColumnName` attribute. The `Label` is used to create and train the model, and it's also used with a second dataset to evaluate the model. The `PredictedLabel` is used during prediction and evaluation. For evaluation, an input with training data, the predicted values, and the model are used. In the *Program.cs* file, replace the `Console.WriteLine("Hello World!")` line with the following code in the `Main` method: @@ -149,7 +147,7 @@ The object is the first part of the pipeline, Pre-processing and cleaning data are important tasks that occur before a dataset is used effectively for machine learning. Raw data is often noisy and unreliable, and may be missing values. Using data without these modeling tasks can produce misleading results. ML.NET's transform pipelines allow you to compose a custom set of transforms that are applied to your data before training or testing. The transforms' primary purpose is for data featurization. A transform pipeline's advantage is that after transform pipeline definition, save the pipeline to apply it to test data. -Apply a to convert the `SentimentText` column into a numeric vector called `Features` used by the machine learning algorithm. This is the preprocessing/featurization step. Using additional components available in ML.NET can enable better results with your model. Add `TextFeaturizer` to the pipeline as the next line of code: +Apply a to convert the `SentimentText` column into a [numeric vector](../resources/glossary.md#numerical-feature-vector) called `Features` used by the machine learning algorithm. This is the preprocessing/featurization step. Using additional components available in ML.NET can enable better results with your model. Add `TextFeaturizer` to the pipeline as the next line of code: [!code-csharp[TextFeaturizer](../../../samples/machine-learning/tutorials/SentimentAnalysis/Program.cs#7 "Add a TextFeaturizer to the pipeline")] @@ -167,7 +165,7 @@ Classification tasks are frequently one of the following types: * Binary: either A or B. * Multiclass: multiple categories that can be predicted by using a single model. -The object is a decision tree learner you'll use in this pipeline. Similar to the featurization step, trying out different learners available in ML.NET and changing their parameters leads to different results. For tuning, you can set hyperparameters like , , and . These hyperparameters are set before anything affects the model and are model specific. They're used to tune the decision tree for performance, so larger values can negatively impact performance. +The object is a decision tree learner you'll use in this pipeline. Similar to the featurization step, trying out different learners available in ML.NET and changing their parameters leads to different results. For tuning, you can set [hyperparameters](../resources/glossary.md#hyperparameter) like , , and . These hyperparameters are set before anything affects the model and are model-specific. They're used to tune the decision tree for performance, so larger values can negatively impact performance. Add the following code to the `TrainAndPredict` method: @@ -181,7 +179,7 @@ Add the following code to the `TrainAndPredict` method: [!code-csharp[TrainModel](../../../samples/machine-learning/tutorials/SentimentAnalysis/Program.cs#9 "Train the model")] -## Predict the model +## Predict the test data outcomes with the model Add some comments to test the trained model's predictions in the `TrainAndPredict` method: @@ -210,7 +208,7 @@ To do that, right-click on the project node in **Solution Explorer** and select #### Return the model trained to use for evaluation -Return the model at the end of the `TrainAndPredict` method. At this point, you could then save it to a zip file or continue to work with it. For this tutorial, you're going to work with it, so add the following code to the next line in `TrainAndPredict`: +Return the model at the end of the `TrainAndPredict` method. At this point, you have a model that can be integrated into any of your existing or new .NET applications, or continue to work with it. For this tutorial, you're going to work with it, so add the following code to the next line in `TrainAndPredict`: [!code-csharp[ReturnModel](../../../samples/machine-learning/tutorials/SentimentAnalysis/Program.cs#15 "Return the model")] @@ -243,7 +241,7 @@ The contains the overall ### Displaying the metrics for model validation -Use the following code to display the metrics, share the results, and act on them accordingly: +Use the following code to display the metrics, share the results, and then act on them: [!code-csharp[DisplayMetrics](../../../samples/machine-learning/tutorials/SentimentAnalysis/Program.cs#21 "Display selected metrics")] @@ -252,18 +250,19 @@ Use the following code to display the metrics, share the results, and act on the Your results should be similar to the following. As the pipeline processes, it displays messages. You may see warnings, or processing messages. These have been removed from the following results for clarity. ``` + Sentiment Predictions --------------------- -Sentiment: Contoso's 11 is a wonderful experience | Prediction: Positive -Sentiment:The acting in this movie is really bad | Prediction: Negative -Sentiment: Joe versus the Volcano Coffee Company is a great film. | Prediction: Positive +Sentiment: Please refrain from adding nonsense to Wikipedia. | Prediction: Negative +Sentiment: He is the best, and the article should say that. | Prediction: Positive PredictionModel quality metrics evaluation ------------------------------------------ -Accuracy: 67.30% -Auc: 73.78% -F1Score: 65.25% +Accuracy: 66.67% +Auc: 94.44% +F1Score: 75.00% + ``` Congratulations! You've now successfully built a machine learning model for classifying and predicting messages sentiment. You can find the source code for this tutorial at the [dotnet/samples](https://github.com/dotnet/samples/tree/master/machine-learning/tutorials/SentimentAnalysis) repository. @@ -276,7 +275,7 @@ In this tutorial, you learned how to: > * Create the learning pipeline > * Load a classifier > * Train the model -> * Predict the model +> * Predict the test data outcomes with the model > * Evaluate the model with a different dataset Advance to the next tutorial to learn more