Diskuze: this v parametru

C# .NET .NET (C# a Visual Basic) this v parametru American English version English version

Avatar
jt.e
Člen
Avatar
jt.e:

Ahoj, vysvětlete mi prosím, jaký je rozdíl mezi těmito funkcemi:

string NejakaFunkce(string vstup)
a
string NejakaFunkce(this string vstup)

(jsem začátečník)

Editováno 28.9.2015 12:07
 
Odpovědět 28.9.2015 12:05
Avatar
Odpovídá na jt.e
Michal Štěpánek:

podle mě tam chybí za tím this čárka a pak by to znamenalo, že v parametru posíláš instanci formuláře.

string NejakaFunkce(this, string vstup)
Nahoru Odpovědět  -2 28.9.2015 12:09
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na jt.e
Jan Vargovský:

První je signatura klasické instanční metody. Ta druhá je extension metoda (aby fungovala tak jak má, tak musí být v public static třídě a ta extension metoda musí mít access modifier public).

 
Nahoru Odpovědět 28.9.2015 12:43
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na jt.e
Jan Vargovský:

Nestihl jsem edit... Kdyby se někdo nudil, může to smazat tu předchozí zprávu.

První je signatura klasické instanční metody. Ta druhá je extension metoda (aby fungovala tak jak má, tak musí být v static třídě).

Abys chápal k čemu to je. Dostaneš přístup ke třídě, která je už sealed nebo nemáš možnost změnit typ, který využíváš. Prakticky to budou nějaké knihovny třetích stran. Pak si napíšeš extension metodu, která ti rozšíří tu tvojí instanci. Příklad, který bys pochopil může být třeba rozšíření třídy Random o generování booleanu.

internal static class RandomExtensions
{
    internal static bool NextBoolean(this Random r)
    {
        return r.Next(2) % 2 == 0;
    }
}

Pak to už můžeš normálně zavolat kdekoliv ve tvojí assembly.

Random r = new Random();
bool b = r.NextBoolean();
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
 
Nahoru Odpovědět 28.9.2015 12:50
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:

.. (by jsem pomalejší:))

Editováno 28.9.2015 12:54
 
Nahoru Odpovědět 28.9.2015 12:53
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na jt.e
Jan Vargovský:

Tak by to nebyla extension metoda a musel bys to volat jako

bool b = RandomExtensions.NextBoolean(r);

Takhle tu instanci předáváš, ale v případě extension metody tu metodu voláš jakoby na instanci.

 
Nahoru Odpovědět 28.9.2015 12:54
Avatar
jt.e
Člen
Avatar
Odpovídá na Jan Vargovský
jt.e:

Díky moc. Už to chápu.

 
Nahoru Odpovědět 28.9.2015 12:56
Avatar
vodslon
Člen
Avatar
Odpovídá na jt.e
vodslon:

Ahoj, ono je to takové, prostě je to tak vymyšlené.

Tím this říkáš, že rozšiřuješ třídu tohoto prostoru. Vím, že by to Ing. z Microsoftu asi vysvětlil lépe.

Ale s čím já si vystačím je.

public class MojeTrida()
{

}

a teď si řekneš mě tam chybí metoda kterou bych chtěl použít, máš dvě možnosti bud uděláš odvozenou třídu a k potomkovi přidáš metodu, je to tak správně a má se to tak dělat, ale pokud seš línej uděláš tady to.

internal static class ExtensionTrida
    {
        internal static void NovaMetoda(this MojeTridat mojetrida)
        {

            //code
        }
    }

potom když to máš ve stejném namespacu a vytvoříš si instanci MojeTrida tak v ní máš i metodu nová metoda právě díky tomu this, protože bez toho on by jakoby nevěděl, kam to přiřadit. Prostě tady v tom případě to není jenom vstupní parametr té metody, ale přiřazuje mu tu instanci třídy kterou bude rozšiřovat.

Pokud Tě to mate nepoužívej to.

Editováno 28.9.2015 16:14
 
Nahoru Odpovědět 28.9.2015 16:14
Avatar
jt.e
Člen
Avatar
Odpovídá na vodslon
jt.e:

kupodivu mne to nějak nemate, spíš mne překvapuje, na co všechno tvůrci kompilátoru nemysleli :)
Ale je fakt, že to čitelnosti kódu zrovna nepřidá.

Editováno 28.9.2015 18:44
 
Nahoru Odpovědět 28.9.2015 18:42
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na vodslon
Jan Vargovský:

Namespacy tam nehrají žádnou roli.
Ta metoda v žádném případě nenáleží tomu typu (resp. té instanci). Jinými slovy, ta metoda se k nikomu nepřiřazuje, pořád patří té static třídě.

 
Nahoru Odpovědět 28.9.2015 20:52
Avatar
vodslon
Člen
Avatar
Odpovídá na Jan Vargovský
vodslon:

máš pravdu, jsem rád za Tvé příspěvky, protože vím sice jak to funguje, ale neumím pořádně říct proč, protože ten zápis je tak trochu zmatečný..Snad doufám, že alespon pomohl příklad jak to používám.

 
Nahoru Odpovědět 28.9.2015 22:18
Avatar
coells
Redaktor
Avatar
Odpovídá na vodslon
coells:

Někdy jazyk obsahuje syntaktické prvky [syntaxe = způsob zápisu], které ti mají v určitých případech zjednodušit život.
Pokud takový prvek nemění sémantickou část jazyka [sémantika = význam zápisu], říká se mu syntaktický cukr.

Extension metoda je úplně obyčejná statická metoda, která se jen jinak zapisuje.
Syntaktický cukr spočívá v tom, abys místo ExtensionTrida­.NovaMetoda(mo­jeInstance) mohl napsat mojeInstance.No­vaMetoda()
Významově jsou pak oba zápisy naprosto stejné.

 
Nahoru Odpovědět 28.9.2015 22:37
Avatar
patrik.valkovic
Šéfredaktor
Avatar
patrik.valkovic:

Abych to trošku shrnul - je to syntaktický cukr. Například následující dvě metody jsou použitím naprosto totožné, jde pouze o zápis jejich volání.

internal static class RandomExtensions
{
    public static bool NextBoolean(this Random r)
    {
        return r.Next(2) % 2 == 0;
    }

    public static bool NextBoolean(Random r)
    {
        return r.Next(2) % 2 == 0;
    }
}
Random r = new Random();
bool b = r.NextBoolean();
bool c = RandomExtensions.NextBoolean(r);

Vidíš, že kód je přehlednější a lée vystihuje význam, ve kterém bylo myšleno metodu použít. IntelliSense ti sám napovídá rozšiřující metody atd. například když používáš List, drtivá většina jeho metod jsou pouze rozšiřující (Aggregate, Sum, atd), sám List moc metod nemá - https://msdn.microsoft.com/….110%29.aspx. Nikde tam metody jako Sum, Any a podobné nenajdeš - ty jsou až rozšiřující.

Co se týče k tomu, co řekl vodslon - rozhodně to není myšleno tak, že se ti nechce odvozovat tříd, tak si radši vytvoříš rozšiřující metodu. Je několik případů, kdy dává použití rozšiřující metody smysl.

  • Třída, kterou upravuješ, je zapečetěná. Například u knihoven třetích stran. Vlastní třídu si tedy vytvořit nemůžeš. U spousty takových tříd ani nevíš, jak je třída implementována, takže upravovat ji by byla prakticky sebevražda.
  • Nechceš komplikovat rozhraní třídy. Když je operace, na kterou ti stačí již existující rozhraní, bylo by zbytečné do třídy vkládat další metodu, která by svým způsobem jen reprezentovala již existující rozhraní jen v jiném formátu řekněme. Například máš tíu, která ti vrací List a potřebuješ z toho dostat jednoduché pole. Proč vkládat do třídy metodu, která by vlastně vzala List a vytvořila z něj pole, a tím komplikovat samotnou třídu? Stejný efekt dostaneš rozšiřující metodou.
  • Metoda lze použít pro více tříd. Takové metody jsou právě All, Any, Sum, atd. Ve většině případů neberou konkrétní instanci (List, Queue, Array), ale IEnumerable. Tím lze tu stejnou metodu se stejnou implementací použít pro více kontejnerů. Dokážeš si představit, kdyby měla každá třída implementovat celý ten seznam metod samostatně?
Nahoru Odpovědět  -1 28.9.2015 23:11
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na patrik.valkovic
Jan Vargovský:

Četl jsem prvních pár slov a už je to špatně... Extension metodu můžeš volat i normálně, tak jak to ve skutečnosti udělá kompilátor.

 
Nahoru Odpovědět 28.9.2015 23:27
Avatar
Jan Vargovský
Redaktor
Avatar
Jan Vargovský:

Btw, vůbec nechápu, proč to tu vysvětlujete už potřetí, když to bylo dávno uzavřené ze strany tázajícího.

 
Nahoru Odpovědět 28.9.2015 23:31
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na patrik.valkovic
Jan Vargovský:

Ok, už jsem to dočetl, nevím proč do toho taháš ještě LINQ :D

 
Nahoru Odpovědět 28.9.2015 23:36
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 18 zpráv z 18.