Last active
May 29, 2024 01:57
-
-
Save pielegacy/c090fdbae65045d5a1ee31615a604dc5 to your computer and use it in GitHub Desktop.
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
using System.Diagnostics.CodeAnalysis; | |
using System.Net.Http.Json; | |
using System.Text.Json.Serialization; | |
var httpClient = new HttpClient(); | |
try | |
{ | |
// Section 1 - async I/O | |
/** | |
* 1. Sending a GET request to "https://jsonplaceholder.typicode.com/posts" | |
* 2. Validating that a 200 response was provided - if not, we get an exception | |
* 3. Based on the provided generic type (in this case IEnumerable<Post>) we essentially convert the string content of the response to | |
* a valid C# object. | |
* 4. Assign that object to the variable `posts` | |
**/ | |
var posts = await httpClient.GetFromJsonAsync<IEnumerable<Post>>("https://jsonplaceholder.typicode.com/posts") ?? throw new Exception("Posts failed to retrieve"); | |
/** Section 2 - LINQ | |
* LINQ is a very elegant way of filtering, mapping and reducing data | |
* - Filter (.Where) = As the name implies, filter. The .Where method is the default means of filtering a collection | |
* - Mapping (.Select) = The process of taking in an input collection and for each item transforming the contents of the collection | |
* - Reducing (.Aggregate) = Bottom of the iceberg, reducing is technically a superset of the previously mentioned two but essentially is taking an input and completely "reducing" that input to something else | |
*/ | |
// Basic example of filtering | |
var allPostsWithMoreThan30CharactersInTitle = posts.Where(post => post.Title.Length > 30); | |
PrintPosts(allPostsWithMoreThan30CharactersInTitle); | |
// For individual items, use First/FirstOrDefault | |
var firstBigPost = posts.FirstOrDefault(post => post.Title.Length > 30); | |
if (firstBigPost != null) | |
{ | |
PrintPosts([firstBigPost]); | |
} | |
// LINQ is important because it's IMMUTABLE, anything that happens in LINQ doesn't screw with the underlying collection | |
// This is also a potential PERFORMANCE ISSUE, however we will let you know if that is the case (premature optimisation is the root of all evil) | |
// LINQ essentially iterates over every item in a collection and runs the provided function, this means that with bigger collections - you get poorer performance | |
// Mapping is the process of taking in an input and returning a modified output | |
var postAnalytics = posts.Select(post => new PostAnalytics(post)); | |
foreach (var analytics in postAnalytics) | |
{ | |
PrintAnalytics(analytics); | |
} | |
// You can "chain" LINQ methods | |
var allPostsWithMoreThan30CharactersInTitleAnalytics = posts | |
.Where(post => post.Title.Length > 30) | |
.Select(post => new PostAnalytics(post)); | |
// Aggregate/Reduce is the most powerful of the bunch but it's a pest to write sometimes and nowhere near as clean | |
// as its cousins. | |
var postSummary = posts.Aggregate( | |
new PostCollectionSummary(), | |
(summary, post) => | |
{ | |
summary.PostCount += 1; | |
// If I haven't found a post yet OR the current post is longer, update the lengthiest post | |
if (summary.LengthiestPost == null || post.Title.Length > summary.LengthiestPost.Title.Length) | |
{ | |
summary.LengthiestPost = post; | |
} | |
return summary; | |
}); | |
) | |
Console.WriteLine($"SUMMARY | COUNT: {postSummary.PostCount} | Lengthiest Post: {postSummary.LengthiestPost?.Title}"); | |
} | |
// Exception is the base class for all exceptions | |
// If you provide a specific type that isn't exception, it will only catch that type and all sub-classes | |
catch (Exception ex) | |
{ | |
Console.WriteLine($"Something went wrong ({ex.Message})"); | |
} | |
static void PrintPosts(IEnumerable<Post> posts) | |
{ | |
foreach (var post in posts) | |
{ | |
Console.WriteLine($"Post #{post.Id} - {post.Title}"); | |
} | |
} | |
static void PrintAnalytics(PostAnalytics postAnalytics) | |
{ | |
Console.WriteLine($"Title Length: {postAnalytics.TitleLength}, Vowel Count: {postAnalytics.VowelCountKinda}"); | |
} | |
// { | |
// "userId": 1, | |
// "id": 1, | |
// "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", | |
public sealed class Post | |
{ | |
[JsonPropertyName("id")] | |
public int Id { get; set; } = 0; | |
[JsonPropertyName("title")] | |
public string Title { get; set; } = string.Empty; | |
} | |
public sealed record PostAnalytics(Post post) | |
{ | |
public int TitleLength => post.Title.Length; | |
public int VowelCountKinda => post.Title.ToLower().Count(c => c == 'a' || c == 'i' || c == 'o'); | |
} | |
public sealed class PostCollectionSummary | |
{ | |
public int PostCount { get; set; } | |
public Post? LengthiestPost { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment