Skip to content

Instantly share code, notes, and snippets.

@pielegacy
Last active May 29, 2024 01:57
Show Gist options
  • Save pielegacy/c090fdbae65045d5a1ee31615a604dc5 to your computer and use it in GitHub Desktop.
Save pielegacy/c090fdbae65045d5a1ee31615a604dc5 to your computer and use it in GitHub Desktop.
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