-
-
Notifications
You must be signed in to change notification settings - Fork 366
Implement new concept exercise for extension methods #1585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
f0f6eb5
concept/extension-methods docs
b488af6
calculator-extension code files
f704f69
calculator-extension docs
303d596
update list of implemented exercises
c6bf7eb
Update exercises/concept/calculator-extensions/CalculatorExtensions.c…
yzAlvin 89ec8b9
Update concepts/extension-methods/introduction.md
yzAlvin 2a12b5b
Update concepts/extension-methods/about.md
yzAlvin 1479c38
improve documentation
542a0e0
log extension method exercise
48b3385
added log exercise to config.json
84ac2e3
instructions for exercise
0ec63b3
merge conflict
2a5dd8e
Update exercises/concept/log-analysis/.docs/instructions.md
yzAlvin add9d0c
Update exercises/concept/log-analysis/.docs/instructions.md
yzAlvin b7c8fff
Update exercises/concept/log-analysis/.docs/instructions.md
yzAlvin ddaae8b
Update exercises/concept/log-analysis/LogAnalysis.csproj
yzAlvin 9f83ca5
Update exercises/concept/log-analysis/.meta/config.json
yzAlvin 7f2a9fd
Update exercises/concept/log-analysis/.docs/introduction.md
yzAlvin 22645de
Update exercises/concept/calculator-conundrum/CalculatorConundrum.cs
yzAlvin 2b0cc06
Update exercises/concept/log-analysis/.docs/hints.md
yzAlvin 24da38d
update docs
3770c25
update code files
5d458f1
Update exercises/concept/log-analysis/.docs/hints.md
yzAlvin 22437c2
Update exercises/concept/log-analysis/.docs/hints.md
yzAlvin f0dd81e
Update exercises/concept/log-analysis/.docs/instructions.md
yzAlvin 8520235
Update exercises/concept/log-analysis/LogAnalysis.cs
yzAlvin ec8c825
Update exercises/concept/log-analysis/.docs/instructions.md
yzAlvin 5227af3
Update config.json
yzAlvin 8e6c7fd
Update config.json
yzAlvin 9771aeb
Update exercises/concept/log-analysis/.docs/instructions.md
yzAlvin 30efa9d
Update exercises/concept/log-analysis/.docs/instructions.md
yzAlvin 92155c9
Update instructions.md
yzAlvin 240d946
Update Exemplar.cs
yzAlvin c788161
add mention of namespace import
152e084
add test case
18673bb
Update exercises/concept/log-analysis/.docs/instructions.md
yzAlvin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"blurb": "Extension methods allow you to add methods to existing types.", | ||
"authors": [ | ||
"yzAlvin" | ||
] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# About | ||
|
||
[Extension methods][extension-methods] allow adding methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. | ||
|
||
Extension methods are brought into scope at the namespace level. | ||
|
||
Extension methods are static methods, but they're called as if they were instance methods on the extended type. It achieves this by using `this` before the type, indicating the instance we put the `.` on is passed as the first parameter. For client code, there's no apparent difference between calling an extension method and the methods defined in a type. | ||
|
||
```csharp | ||
public static int WordCount(this string str) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be nice to be a bit more explicit here and give the class a namespace, and then have a second code sample indicating another file that has a |
||
{ | ||
return str.Split().Length; | ||
} | ||
|
||
"Hello World".WordCount(); | ||
// => 2 | ||
``` | ||
|
||
A well-known example of extension methods are the [LINQ][linq] standard query operators that add query functionality to the existing IEnumerable types. | ||
|
||
[linq]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/ | ||
[extension-methods]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Introduction | ||
|
||
Extension methods allow adding methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. They are defined as static methods but are called by using instance method syntax. Their first parameter is preceded by the `this` modifier, and specifies which type the method operates on, and are brought into scope at the namespace level. | ||
|
||
```csharp | ||
public static int WordCount(this string str) | ||
{ | ||
return str.Split().Length; | ||
} | ||
|
||
"Hello World".WordCount(); | ||
// => 2 | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[ | ||
{ | ||
"url": "https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods", | ||
"description": "extension-methods" | ||
} | ||
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Hints | ||
|
||
## General | ||
|
||
- All extension methods must be marked `static`. | ||
- All extension methods must have `this` before the first argument | ||
|
||
## 1. Implement the extension method SubstringAfter | ||
|
||
- Different options to search for text in a string are explored in [this tutorial][tutorial-docs.microsoft.com-search-text-in-string]. | ||
|
||
## 2. Implement the extension method SubstringBetween | ||
|
||
- Different options to search for text in a string are explored in [this tutorial][tutorial-docs.microsoft.com-search-text-in-string]. | ||
|
||
## 3. Parse message in a log | ||
|
||
- You can re-use the `SubstringAfter()` extension method here. | ||
|
||
## 4. Parse log level in a log | ||
|
||
- You can re-use the `SubstringBetween()` extension method here. | ||
|
||
[tutorial-csharp.net-strings]: https://csharp.net-tutorials.com/data-types/strings/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Instructions | ||
|
||
In this exercise you'll be processing log-lines. | ||
|
||
Each log line is a string formatted as follows: `"[<LEVEL>]: <MESSAGE>"`. | ||
|
||
There are three different log levels: | ||
|
||
- `INFO` | ||
- `WARNING` | ||
- `ERROR` | ||
|
||
You have several tasks, each of which will take a log line and ask you to do something with it. | ||
|
||
## 1. Allow retrieving the string after a specific substring | ||
|
||
Looking at the logs of the last month, you see that the test message is always located after a specific substring. As you're anticipating having to extract the test message sometime in the near future, you decide to create a helper method to help you with that. | ||
|
||
Implement the (_static_) `LogAnalysis.SubstringAfter()` extension method, that takes in some string delimeter and returns the substring after the delimiter. | ||
yzAlvin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```csharp | ||
var log = "[INFO]: File Deleted."; | ||
log.SubstringAfter(": "); // => returns "File Deleted." | ||
``` | ||
|
||
## 2. Allow retrieving the string in between two substrings | ||
|
||
On further inspection, you see that the log level is always located between square brackets (`[` and `]`). As you're also anticipating having to extract the log level sometime in the near future, you decide to create a another helper method to help you with that. | ||
|
||
Implement the (_static_) `LogAnalysis.SubstringBetween()` extension method that takes in two string delimeters, and returns the substring that lies between the two delimeters. | ||
|
||
```csharp | ||
var log = "[INFO]: File Deleted."; | ||
log.SubstringBetween("[", "]"); // => returns "INFO" | ||
``` | ||
|
||
## 3. Parse message in a log | ||
|
||
Implement the (_static_) `LogAnalysis.Message()` extension method to return the message contained in a log. | ||
|
||
```csharp | ||
var log = "[ERROR]: Missing ; on line 20."; | ||
log.Message(); // => returns "Missing ; on line 20." | ||
``` | ||
|
||
## 4. Parse log level in a log | ||
|
||
Implement the (_static_) `LogAnalysis.LogLevel()` extension method to return the log level of a log. | ||
|
||
```csharp | ||
var log = "[ERROR]: Missing ; on line 20."; | ||
log.LogLevel(); // => returns "ERROR" | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Introduction | ||
|
||
Extension methods allow adding methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. They are defined as static methods but are called by using instance method syntax. Their first parameter is preceded by the 'this' modifier, and specifies which type the method operates on. | ||
|
||
```csharp | ||
public static int WordCount(this string str) | ||
{ | ||
return str.Split().Length; | ||
} | ||
"Hello World".WordCount(); | ||
// => 2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System; | ||
|
||
public static class LogAnalysis | ||
yzAlvin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
public static string SubstringAfter(this string str, string delimiter) | ||
{ | ||
return str.Substring(str.IndexOf(delimiter) + delimiter.Length); | ||
} | ||
|
||
public static string SubstringBetween(this string str, string start, string stop) | ||
{ | ||
return str.SubstringAfter(start).Substring(0, str.IndexOf(stop) - 1); | ||
} | ||
|
||
public static string Message(this string log) | ||
{ | ||
return log.SubstringAfter("]: "); | ||
} | ||
|
||
public static string LogLevel(this string log) | ||
{ | ||
return log.SubstringBetween("[", "]"); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"blurb": "Learn about extension-methods by analysing logs.", | ||
"icon": "log-levels", | ||
"authors": [ | ||
yzAlvin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"yzAlvin" | ||
], | ||
"files": { | ||
"solution": [ | ||
"LogAnalysis.cs" | ||
], | ||
"test": [ | ||
"LogAnalysisTests.cs" | ||
], | ||
"exemplar": [ | ||
".meta/Exemplar.cs" | ||
] | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Design | ||
|
||
## Goal | ||
|
||
The goal of this exercise is to teach the student the Concept of Extension Methods in C#. | ||
|
||
## Learning objectives | ||
|
||
- Know what extension methods are. | ||
- Know how to define extension methods on reference and value types | ||
|
||
## Out of scope | ||
|
||
- Assemblies. | ||
|
||
## Concepts | ||
|
||
- `extension-methods`: know what extension methods are; know how to define extension methods on reference and value types. | ||
|
||
## Prerequisites | ||
|
||
- `classes`: know what instance methods are. | ||
- `namespaces`: know what namespaces are; know how to import namespaces. | ||
- `collections`: know what collections are. | ||
|
||
## Resources to refer to | ||
|
||
### Hints | ||
|
||
- [Extension methods][extension-methods]: how to define extension methods. | ||
- [Namespaces][namespaces]: how to define an import namespaces. | ||
- [Collections][collections]: what a collections is. | ||
|
||
### After | ||
|
||
- [Extension methods][extension-methods]: how to define extension methods. | ||
- [Namespaces][namespaces]: how to define an import namespaces. | ||
- [Collections][collections]: what a collections is. | ||
|
||
[extension-methods]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods | ||
[namespaces]: https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/types/namespaces | ||
[collections]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/collections |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System; | ||
|
||
public static class LogAnalysis | ||
{ | ||
// TODO: define the 'SubstringAfter()' extension method on the `string` type | ||
|
||
// TODO: define the 'SubstringBetween()' extension method on the `string` type | ||
|
||
// TODO: define the 'Message()' extension method on the `string` type | ||
|
||
// TODO: define the 'LogLevel()' extension method on the `string` type | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net5.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> | ||
<PackageReference Include="xunit" Version="2.4.1" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> | ||
<PackageReference Include="Exercism.Tests" Version="0.1.0-beta1" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using Xunit; | ||
using Exercism.Tests; | ||
using System; | ||
|
||
public class LogAnalysisTests | ||
{ | ||
[Fact] | ||
public void SubstringAfter_WithDelimeterOfLength1() | ||
{ | ||
Assert.Equal(" am the 1st test", "I am the 1st test".SubstringAfter("I")); | ||
} | ||
|
||
[Fact(Skip = "Remove this Skip property to run this test")] | ||
public void SubstringAfter_WithDelimeterOfLengthLongerThan1() | ||
{ | ||
Assert.Equal(" test", "I am the 2nd test".SubstringAfter("2nd")); | ||
} | ||
|
||
[Fact(Skip = "Remove this Skip property to run this test")] | ||
public void SubstringBetween() | ||
{ | ||
Assert.Equal("INFO", "[INFO]: File Deleted.".SubstringBetween("[", "]")); | ||
} | ||
|
||
[Fact(Skip = "Remove this Skip property to run this test")] | ||
public void Message() | ||
{ | ||
var log = "[WARNING]: Library is deprecated."; | ||
Assert.Equal("Library is deprecated.", log.Message()); | ||
} | ||
|
||
[Fact(Skip = "Remove this Skip property to run this test")] | ||
public void LogLevel() | ||
{ | ||
var log = "[WARNING]: Library is deprecated."; | ||
Assert.Equal("WARNING", log.LogLevel());; | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.