Odfláknutá dokumentace v MSDN   zodpovězená otázka

VB.NET

'System.Collections.Concurrent.ConcurrentDictionary(Of TKey, TValue)

Public Function AddOrUpdate (
  key As TKey,
  addValue As TValue,
  updateValueFactory As Func(Of TKey, TValue, TValue)
) As TValue

Co je druhý a třetí parametr u aktualizační anonymní metody? MSDN dokumentace je v některých místech jako např. tady neskutečně odfláknutá a na stejný dotaz, který byl položen před třemi roky tam dosud nikdo nebyl schopen odpovědět. Předpokládám, že jedno z toho je původní hodnota a to druhé nová hodnota. Na zkoušení jak to funguje nebo Reflector nemám čas ani náladu.

nahlásit spamnahlásit spam -10 / 10 odpovědětodpovědět

Dokumentace je mizerná, nicméně zrovna tady je z názvu parametrů zřejmé, co to dělá.

addValue je hodnota, která se přidá, pokud ve slovníku tam záznam nebyl.

updateValueFactory je funkce, která dostane stávající klíč a stávající hodnotu a vyplivne novou hodnotu, která se tam má uložit (update).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nevím, zda si rozumíme. Konkrétně mi jde o toto:

updateValueFactory As Func(Of TKey, TValue, TValue)

TKey je bez debaty klíč. Co je ale první TValue a druhé TValue?

Anderson se ptá na to samé, viz. http://msdn.microsoft.com/en-us/library/...

nahlásit spamnahlásit spam -13 / 13 odpovědětodpovědět

První TValue je ještě parametr funkce. Druhé TValue je návratová hodnota.

Funkce, kterou do tohoto parametru narvete, vypadá třeba takto:

Function (key As TKey, oldValue As TValue) As TValue
    '...
    'Return newValue
End Function

Prostě funkce, která dostane to, co ve slovníku aktuálně je (klíč a hodnotu) a má vrátit novou hodnotu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Potom ale nechápu, k čemu taková idiotština je, když ta funkce vůbec nedostává parametr s novou hodnotou. Nenapadá mě jediný případ, kde by to bylo k něčemu použitelné.

Imports System.Collections.Concurrent
Module Module1
  Sub Main()
    Dim cd As New ConcurrentDictionary(Of Integer, String)
    cd.TryAdd(1, "a")
    cd.TryAdd(2, "b")
    cd.TryAdd(3, "c")
    cd.AddOrUpdate(2, "x", AddressOf AddOrUpdate)
  End Sub
  Function AddOrUpdate(key As Integer, oldValue As String) As String
    'V key bude 2, v oldValue bude b.
    Return oldValue
  End Function
End Module

V tomto případě vůbec neproběhne aktualizace 2,b na 2,x. Buď je to skutečně tak debilní, že je to naprosto k ničemu a je potřeba použít TryRemove+TryAdd, nebo mi uniká něco zásadního.

nahlásit spamnahlásit spam -13 / 13 odpovědětodpovědět

Skúste:

Imports System.Collections.Concurrent
Module Module1
  Sub Main()
    Dim cd As New ConcurrentDictionary(Of Integer, String)
    cd.TryAdd(1, "a")
    cd.TryAdd(2, "b")
    cd.TryAdd(3, "c")
    cd.AddOrUpdate(2, "x", AddressOf AddOrUpdate)
  End Sub
  Function AddOrUpdate(key As Integer, oldValue As String) As String
    'V key bude 2, v oldValue bude b.
    Return "newval"
  End Function
End Module
nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

K čemu mi bude taková hovadina, když potřebuju dostat tu novou hodnotu zvenčí do té metody?!?!

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

K tomu Vám bude takáto hovadina, že uupdateValueFactory má na základe kľúča a aktuálnej hodnoty vrátiť novú hodnotu. Ale len na základe kľúča a starej hodnoty.

Takže do updateValueFactory nie je možné predať ako parameter novú hodnotu, k tomu sú iné metódy triedy ConcurrentDictionary.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Ano, přesně takováhle hovadina je v praxi k ničemu. K čemu mi bude původní hodnota, když potřebuju aktualizovat novými, ve slovníku ještě neobsaženými údaji?

k tomu sú iné metódy triedy ConcurrentDictionaryJaké?

nahlásit spamnahlásit spam -12 / 12 odpovědětodpovědět

Absolutně to nechápete, a přitom je to tak prosté. Ta funkce nedostává novou hodnotu jako parametr, ale vrací ji.

Pokud do Dictionary chcete uložit hodnotu, kterou máte již v nějaké proměnné, nebo je to konstanta, pak AddOrUpdate nepotřebujete a použijete cd(klíč) = hodnota.

AddOrUpdate se používá ve chvíli, kdy chcete hodnotu vypočítat podle toho, jestli už v tom slovníku nějaká je (a případně podle toho, jaká je ta aktuální hodnota).

Např. budu mít kolekci objektů a budu si chtít inkrementovat pokaždé, když daný objekt použiju. Tak udělám ConcurrentDictionary(Of Object, Integer) a inkrementaci provedu takhle:

cd.AddOrUpdate(pouzityObjekt, 1, Function(key, oldValue) oldValue + 1)

Pokud tam nic nebylo, dá se tam 1. Pokud tam už hodnota byla, dá se tam aktuální hodnota + 1.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Chápu to přesně podle toho, jak (kriplovsky) je to popsané v MSDN. Tudíž od AddOrUpdate očekávám, že ta metoda slouží pro přidání hodnoty předané metodě v případě, že klíč neexistuje a aktualizaci (nahrazení) hodnoty v případě, že klíč existuje. K čemu je aktualizace něčeho, když neznám aktualizační hodnoty kromě původní hodnoty? Nějaká inkrementace je v praxi k ničemu a dá se provést jinak a jednoduššeji. Celé AddOrUpdate je jeden velký epic fail.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Prvý argument AddOrUpdate je kľúč, druhý je hodnota, ktorú pridá, ak v slovníku ešte nie je daný kľúč, nuž a v treťom je funkcia, ktorá na základe kľúča a starej hodnoty vráti novú hodnotu.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Byl bych velice rád kdyby ti, co odpovídají, alespoň zhruba tušili, o co mi jde...

nahlásit spamnahlásit spam -9 / 9 odpovědětodpovědět

Jsou 3 situace:

1) Chci, aby ve slovníku pod nějakým klíčem byla třeba hodnota 5 - je mi jedno, jestli tam pod tím klíčem už něco bylo, nebo ne. Pak napíšu:

cd("key") = 5

Mohl bych napsat i tohle, ale je to delší:

Dim hodnota = 5
cd.AddOrUpdate("key", hodnota, Function(k, ov) hodnota)

2) Chci, aby se do slovníku uložila 5, pokud tam nic nebylo, a 10, pokud tam už nějaká hodnota byla. Pak napíšu

Dim hodnota = 10
cd.AddOrUpdate("key", 5, Function(k, ov) hodnota)

3) Chci, aby se do slovníku uložila 5, pokud tam nic nebylo, a pokud tam něco bylo, potřebuji tam dát hodnotu, která závisí na tom, co ve slovníku bylo (např. ta inkrementace, o které jsem psal):

cd.AddOrUpdate("key", 5, Function(k, oldValue) 
                            'zde si vypočítám hodnotu, kterou do slovníku chci uložit, na základě oldValue
                         End Function)

Funkce AddOrUpdate je takhle udělána kvůli třetímu případu, který je občas potřeba.

Btw až teď jsem si uvědomil, že to možná nechápete proto, že netušíte, že lambda funkce podporují closures, tedy že v nich můžete používat proměnné deklarované ve funkcích, které tu lambdu obsahují. Výstupní hodnotu do lambdy tedy dostanete snadno, stačí ji mít v nějaké proměnné.

A mimochodem by mě zajímalo, jak byste dělal tu inkrementaci - máte 10 objektů a ke každému si potřebujete při nějaké události thread-safe inkrementovat číslo, a přitom tuto informaci nechcete cpát do těch objektů samých. ConcurrentDictionary a postup, který jsem uvedl předtím, je úplně ideální řešení.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Btw) Novinka ve 4.0+, nevěděl jsem.

A mimochodem) 10 objektů, ke každému inkrementovat číslo. Co bude klíč a co hodnota? Obvykle je potřeba identifikátor objektu jako klíč a objekt jako hodnota. Na číslo už nezbývá místo.

nahlásit spamnahlásit spam -9 / 9 odpovědětodpovědět

No klíčem může být přímo ten objekt a hodnotou integer, kolikrát byl použit.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

No to přece musíte uznat sám, že je totální hovadina. Nebudu se ve slovníku orientovat podle reference, ale podle klíče! Tudíž jako klíč musí být nějaký unikátní identifikátor objektu.

nahlásit spamnahlásit spam -9 / 9 odpovědětodpovědět

Reference uz je unikatni identifikator objektu.

Samozrejme pokud v objektu uz existuje nejaka unikatne identifikujici vlastnost, da se pouzit i ta, ale specialne kvuli tomu bych ji nezakladal - dat objekt samotny jako klic neni problem ani hovadina, ale zcela legalni postup.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V praxi se ve slovníku orientovat pomocí referencí je do nebe volající nukleární hovadina...

nahlásit spamnahlásit spam -9 / 9 odpovědětodpovědět

A nějaký validní argument kromě "říká to Linhart" by nebyl?

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Říká to Herceg?

Konflikt bych ukončil se závěrem, že:

- Dokumentace v MSDN je nedostatečná.

- AddOrUpdate nefunguje tak, jak by měla, popř. by se měla jmenovat jinak.

nahlásit spamnahlásit spam -9 / 9 odpovědětodpovědět

Já si svůj postoj obhájil - pro účely klíče nevidím důvod zavádět speciální identifikátor, když jako klíč mohu použít objekt.

Váš jediný argument pro zavádění umělého klíče byl, že neudělat to je hovadina.

Souhlasím s tím, že dokumentace v MSDN je nedostatečná, ale AddOrUpdate funguje správně a je navržena tak, aby se dala použít pro všechny 3 situace, které jsem vyjmenoval výše. S názvem problém není, ona opravdu udělá Add nebo Update podle situace.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ne, můj argument byl, že reference jako klíč je v praxi nepoužitelná (použitelná s velkými obtížemi). Mě nezajímá teorie jaké všechny věci se s tím dají dělat, ale praktické využití v konkrétních případech. Primitivní datové typy jako Integer se ve slovníku v běžných aplikacích vyskytovat nebudou vůbec, nebo minimálně.

nahlásit spamnahlásit spam -4 / 4 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback