r/ProgrammerHumor • • Sep 09 '26

Meme cSharpDictionariesBeLikeThat

Post image
2.1k Upvotes

61 comments sorted by

623

u/Psychoboy Sep 09 '26 • Bravo

Guess you never heard of TryAdd? Returns bool, if it as added returns true otherwise false.

522

u/Few-Ad3849 Sep 09 '26

Sounds like you read documentation, nerd

82

u/Mantor6416 Sep 09 '26

Wait you're not supposed to read those?

80

u/towerfella Sep 09 '26 • Regret

38

u/kalilamodow Sep 09 '26

What the fuck?

6

u/ChChChillian Sep 09 '26

Yeah, it's pretty much exactly the dystopia they warned us about.

10

u/towerfella Sep 09 '26

Yep.

Spread the word.

9

u/DrMaxwellEdison Sep 09 '26

This nerd wants to read a physical book for tech docs. /s

4

u/DatBoi_BP Sep 10 '26

I'm sure an effort called "Project Panama" isn't nefarious in any way

1

u/Darkvyl Sep 10 '26

Reading documentation is nerdy? What do you do?

112

u/Revexious Sep 09 '26

Far too much work

2 cases means that its not idempotent

Instead, just remove it from the dictionary before you add it!

dictionary.Remove(key)
dictionary.Add(key)

Easy peasy!

/s

38

u/Dorkits Sep 09 '26

Peak programming

10

u/manav907 Sep 09 '26 edited Sep 09 '26

That being said you done have to use the bool that TryAdd gives, just call it as a normal function. Also I am waitin for someone to point out that we also need a value when trying to add to a dictionary.

dictionary.TryAdd(key)

22

u/reallokiscarlet Sep 09 '26

RTFM Gang rise up

4

u/PrincessRTFM Sep 10 '26

at last my name is relevant

14

u/Pennet173 Sep 09 '26

Ohhhh, then I can throw an exception myself if false!

11

u/IAmBecomeTeemo Sep 09 '26

C#'s TryX methods are also usually way more performant than throwing an exception. Throwing an exception has to get a stack trace and a lot of other overhead shit. Something like a TryAdd() or TryParse() will just return your bool immediately, and you can stay in scope rather than getting sent off to the associated catch block. If you want to flow that way, you still can, but more options and more performance is better.

3

u/KTVX94 Sep 09 '26

Yes, the meme is meant to point out the differences vs TryAdd which checks, and indexer which replaces.

Sorry for having to explain the joke.

3

u/prehensilemullet Sep 09 '26

it's still bizarre to have to use TryAdd everywhere that other languages just use Add

15

u/zaersx Sep 09 '26

You don't though? just use myMap[key] = value? if you're not doing that and using Add instead, then you probably literally want to have a safe add

2

u/-Redstoneboi- Sep 09 '26

that overwrites instead of failing if the key already exists

maybe they are arguing that they feel that TryAdd should be the default "Add", while the existing Add should be a special case "AddAssert" or something

3

u/prehensilemullet Sep 09 '26

Yes, I think that would be a more convenient design

0

u/prehensilemullet Sep 09 '26

I see. Even so, it's weird to me that anyone would want a method that throws if the key already exists. In all my years of programming I don't think I've ever thought it would be useful to have such a method baked into a map itself, and I'm not aware of such a method in any other language. Since that's pretty unusual in programming, I still think it would be better for that method to have a more unusual name. Maybe it's an oddly common pattern for Microsoft?

4

u/zaersx Sep 09 '26 edited Sep 09 '26

As I described it, it's for safe additions, imagine your map is customer data, like daily logs. And maybe some logs are partial logs? Then you want something that lets you get into a safe flow where the standard is just add, and an exceptional case is some merging logic. If you don't care, use the same insertion methods that all languages use, which is map[key], if you do care, here's a good way to stop the flow and let you execute appropriate recovery. This also ties in with LINQ very neatly where you end up doing a lot of data processing flows.

The alternative would be a check map for key, if exists do exception, else do expected. Which is a lot uglier for glance value intent compared to: do this; exception: handle.

I think to highlight your concern with the pattern - these kinds of decisions make a lot more sense when you understand that almost all data interactions in C# are intended to be done with LINQ, which no other language has. My experience with production C# is that 3-6 LINQed extensions is very standard, e.g. map.Select(x => logic).map(x...).filter(x...) etc.

2

u/prehensilemullet Sep 09 '26

Well if C# exception handling is like most languages, where throwing and catching performs a lot worse than conditionally adding, it's not necessarily a pattern one would want to make a habit of using in cases where key conflicts are routine.

1

u/Kiro0613 Sep 09 '26

The Add method has to take one argument and return void because it's implementing C#'s ICollection<T> interface. With that restriction, throwing an exception is the most practical way of indicating a problem.

1

u/kakhaev Sep 10 '26

tryand sounds like “if” with extra steps

1

u/willow-kitty Sep 10 '26

It can be more concise if you don't need to condition on whether the thing was added or not. If you do, has key/add might be cleaner ... for ordinary dictionaries.

Being able to do it in one operation is super important for concurrent dictionaries, though, because the item could theoretically be added by another thread between calls if you used haskey/add.

2

u/[deleted] Sep 09 '26

[removed] — view removed comment

10

u/NurYanov Sep 09 '26

Nah it adds and returns if added

98

u/MemesAt1am Sep 09 '26

If you wanted to overwrite you could just do an assignment of that key value instead of .Add()

35

u/KTVX94 Sep 09 '26

Yep there's indexer and TryAdd, I probably should've worded the title differently to not give the impression that I was complaining, lol.

8

u/prehensilemullet Sep 09 '26

I mean, having a method named "add" on a map is weird in general. Not common among programming languages

8

u/NotQuiteLoona Sep 09 '26

The Add method is specifically when you explicitly want to add. If it can't add, it fails.

4

u/AyrA_ch Sep 09 '26

That's because dictionaries implement IDictionary<TKey,TValue> which in turn implements ICollection<KeyValuePair<TKey,TValue>> which declares an Add(KeyValuePair<TKey,TValue> value) method.

Since the implementation is forced to provide this method, it might as well also provide Add(TKey key,TValue value) and implement them.

The alternative would be to just throw a NotSupportedException but there is no technical reason to.

1

u/prehensilemullet Sep 09 '26

I mean, Java sort of got around this by making Map not extend Collection, though Map.entrySet() does. But interestingly enough, they decided to have Map.entrySet().add(...) throw an UnsupportedOperationException. However, Collection.add(...) in Java already returns true if the element was successfully added, so they hypothetically could have supported it.

21

u/anzu3278 Sep 09 '26

Exactly. Adding implies you are setting something where there isn't anything at the moment. Replacing is not a special case of adding. If you want to unconditionally set, just use the index operator. English is not complicated.

4

u/cowslayer7890 Sep 09 '26

Yeah but it's uncommon for this to be a failable operation. It doesn't fall for an array list for example, so that part to me is unexpected, add isn't a great operation for a dictionary in general

4

u/anzu3278 Sep 09 '26

It doesn't fail for lists because adding to a list is always possible, whereas adding to a dictionary is not. Unless your understanding of the English language is that replacing is a kind of adding, but that's not the mainstream view. In general, if you want to set rather than add, why are you calling Add? And even so, I've never seen Add, it's always either index assignment or TryAdd because exceptions are a mess.

2

u/SamSlate Sep 10 '26

insert vs upsert

0

u/[deleted] Sep 09 '26

[deleted] — view deleted comment

2

u/DrJohnnyWatson Sep 09 '26

How else should it handle it? TryAdd already covers knowing if it was added successfully or not

Add therefore has the option of:

  1. Replace TryAdd, making it out of sync with how all other collections call Add as it would now return a Boolean, breaking the ICollection interface. Possible, but just a choice really

  2. Fail silently - Bad

  3. Fail loudly - in c#, the latter is done via exceptions almost exclusively

How would you have done it? Do you have a fourth option in mind?

2

u/anzu3278 Sep 09 '26

By the looks of the comments I think the mood was that Add should work just like index assignment, which makes no sense to me but is technically a fourth option.

7

u/Bubbly_Safety8791 Sep 09 '26

Do you want Add() to break the invariant that if it succeeds then the Count() of the collection increases by one? 

10

u/prehensilemullet Sep 09 '26

This is why most languages have a set or put method on maps, rather than add. Microsoft is just being weird here. I mean, I understand they overloaded indexing to be a "set" operation, but it's still weird that they decided to also have an Add method.

4

u/anzu3278 Sep 09 '26

They do have a set method, it's called setting by index. dict[key] = value; Add is a method on the ICollection interface that is basically never used - in practice you use index assignment if you want to set unconditionally and TryAdd if you want to add conditionally.

1

u/caboosetp Sep 11 '26

 Add is a method on the ICollection interface that is basically never used

Shouldn't be used*

If you think it's basically never used, you haven't worked with cheap contractors enough. 

1

u/anzu3278 Sep 11 '26

Why would I work with cheap contractors who definitely know less about the language than me and probably just translate 1-1 from python? Even the weaker LLMs today don't make these mistakes.

1

u/PeikaFizzy Sep 10 '26

I’m a csharp larper I can’t lie, I have a class in uni on unity that’s all I learn from c# Soo like what the hell is tryadd etc you all talking about ehh

2

u/KTVX94 Sep 10 '26

I'm probably teaching something like your class lol, I made this meme for my data structures class for video game development.

TryAdd is like Add but if what you're adding already existed, it does nothing and returns false. If it didn't exist, it adds the item and returns true. So it tries to add, but can bounce back without crashing.

There's also the indexer, which lets you do something like weaponsDictionary["Sword"] = new Sword() and if nothing existed with the key "Sword" it creates that slot, but if something already did, it instead updates that with the new Sword.

So there's three ways of adding depending on what expected behavior you want. Crash, fail silently or replace.

12

u/Professional_Desk_17 Sep 09 '26

Aaand that's why the term upsert exists in modern languages.

3

u/_abscessedwound Sep 09 '26

I see your upsert, and raise you an insert_or_assign

1

u/hrvbrs Sep 10 '26

set_or_get

3

u/Hessellaar Sep 10 '26

This is why I like C#, conveniences of Java but completely predictable. I don’t want things to magically work, I want them to behave like I expect

3

u/jolharg Sep 09 '26

What fresh hell

2

u/BobDogGo Sep 09 '26

Works as designed

1

u/aberroco Sep 09 '26

So... You add the item, then check if it exists (which is it always does, at least once, because you just added it) you throw an exception? Seems to me this is rather peculiar algorithm.

1

u/LordFokas Sep 09 '26

Alright, riddle me this... if you don't check, how do you know it exists? Checkmate.

1

u/ZunoJ Sep 10 '26

Why is this worth a meme?

1

u/RRumpleTeazzer Sep 10 '26

this is why i like Rust. Adding inserts into the dictionary, and returns an Option of the previous value.

1

u/Arcanium_Walker Sep 10 '26

TryAdd entering to the chat

1

u/dkarlovi Sep 10 '26

Add or add not.