{"id":349,"date":"2016-04-10T21:00:09","date_gmt":"2016-04-10T19:00:09","guid":{"rendered":"http:\/\/tomaszkacmajor.pl\/?p=349"},"modified":"2016-04-30T18:12:12","modified_gmt":"2016-04-30T16:12:12","slug":"generyczny-megamix","status":"publish","type":"post","link":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/","title":{"rendered":"Generyczny MegaMix"},"content":{"rendered":"<p>Przyjrzymy si\u0119 dzi\u015b metodzie, kt\u00f3ra widnieje na tytu\u0142owym obrazku. Szybki rzut oka: przecie\u017c nic skomplikowanego &#8211; zaledwie par\u0119 linijek kodu. Na pewno jest <font size=4.5><strong>generyczna<\/strong><\/font>, bo wsz\u0119dzie tylko typy: <em>TInput<\/em>, <em>TResult<\/em>&#8230; Mimo wszystko troch\u0119 mi zaj\u0119\u0142o, \u017ceby j\u0105 zrozumie\u0107 i efektywnie z niej korzysta\u0107. Poniewa\u017c bardzo rzadko sam tworz\u0119 takie metody, postanowi\u0142em rozbi\u0107 j\u0105 na czynniki pierwsze.<br \/>\n<!--more--><br \/>\nW trakcie rozgrzebywania ca\u0142kiem poka\u017anych zasob\u00f3w biblioteki Accord.net natkn\u0105\u0142em si\u0119 na cz\u0119sto wyst\u0119puj\u0105cy wzorzec takiej metody. W moich zastosowaniach w projekcie <a href=\"http:\/\/tomaszkacmajor.pl\/index.php\/2016\/03\/19\/flover-project-4\/\" target=\"_blank\">Flover<\/a> s\u0142u\u017cy przede wszystkim do aplikowania jakiej\u015b konkretnej funkcji na ka\u017cdym pikselu obrazu. Przyjmuje tablic\u0119 pikseli np. typu int[][], modyfikuje piksele i zwraca r\u00f3wnie\u017c int[][] albo double[][]. Jak to &#8211; nie wiadomo jaki typ nam zwr\u00f3ci? Ano to jest w\u0142a\u015bnie magia metod generycznych. Przyjrzyjmy si\u0119 tej metodzie w jej ca\u0142ej krasie.<br \/>\n<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static TResult&#x5B;] Apply&lt;TInput, TResult&gt;(this TInput&#x5B;] vector, Func&lt;TInput, int, TResult&gt; func)\r\n{\r\n    TResult&#x5B;] result = new TResult&#x5B;vector.Length];\r\n\r\n    for (int i = 0; i &lt; vector.Length; i++)\r\n        result&#x5B;i] = func(vector&#x5B;i], i);\r\n    return result;\r\n}\r\n<\/pre>\n<p>Poni\u017cej przyk\u0142ad jej wywo\u0142ania. Tutaj ka\u017cdemu pikselowi nadaje si\u0119 kolor segmentu do jakiego ten piksel nale\u017cy. Wykorzystuj\u0119 to np. w algorytmie tworzenia superpikseli <a href=\"http:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/03\/slic-superpiksele\/\" target=\"_blank\">SLIC<\/a>.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npixels = pixels.Apply((x,i)=&gt;kmeans.Clusters.Centroids&#x5B;idx&#x5B;i]]);\r\n<\/pre>\n<p>Mog\u0119 ju\u017c ujawni\u0107, \u017ce nasza metoda jest jednocze\u015bnie:<\/p>\n<ol>\n<li>Rozszerzaj\u0105ca<\/li>\n<li>Generyczna<\/li>\n<li>Przyjmuj\u0105ca generyczny delegat typu <em>Func<\/em><\/li>\n<li>Wywo\u0142ywana z delegatem wyra\u017conym funkcj\u0105 lambda<\/li>\n<\/ol>\n<p>Brzmi okropnie i strasznie! W takim razie po kolei.<\/p>\n<h3>1. Metoda rozszerzaj\u0105ca<\/h3>\n<p>Zajmijmy si\u0119 kluczowym s\u0142owem <font size=4.5><strong>this<\/strong><\/font> widniej\u0105cym przed pierwszym parametrem metody <em>Apply<\/em>. Dzi\u0119ki niemu kompilator wie, \u017ce ma do czynienia z tzw. metod\u0105 rozszerzaj\u0105c\u0105. Metody te s\u0105 pomocne gdy chcemy przeprowadzi\u0107 operacje na jakim\u015b obiekcie (np. dodaj do stringa parametr typu int) albo uzyska\u0107 o nim jakie\u015b informacje (np. policz w stringu litery &#8216;a&#8217;). Niekt\u00f3re z takich operacji jak String.Length czy String.StartsWith() s\u0105 oczywi\u015bcie ju\u017c dost\u0119pne w frameworku. Jednak cz\u0119sto chcemy przecie\u017c dopisa\u0107 nasze w\u0142asne funkcje. Pierwsz\u0105, najcz\u0119stsz\u0105 opcj\u0105 jest podanie obiektu jako argumentu metody. Dodajmy na przyk\u0142ad do stringa &#8220;Score&#8221; parametr typu int, chc\u0105c wypisa\u0107 dla danego ucznia ocen\u0119 z klas\u00f3wki z matematyki.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static string AddIntScore(string str, int parameter)\r\n{\r\n    return str + &quot;: &quot; + parameter.ToString();       \r\n}\r\n<\/pre>\n<p>Wywo\u0142anie takiej metody poni\u017cszym kodem<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n  string s = &quot;Score&quot;;\r\n  string result = &quot;&quot;;\r\n  result = AddIntScore(s, 5);\r\n  Console.WriteLine(result);\r\n<\/pre>\n<p>zwr\u00f3ci nam rezultat:<br \/>\nScore: 5<\/p>\n<p>Jednak czy\u017c nie fajnie by\u0142oby wywo\u0142a\u0107 tak\u0105 metod\u0119 w ten spos\u00f3b?<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n   result = s.AddIntScore(5);\r\n<\/pre>\n<p>Zazwyczaj nie mo\u017cemy bezpo\u015brednio modyfikowa\u0107 klasy obiektu &#8211; tutaj typu string. Ale mo\u017cemy rozszerzy\u0107 j\u0105 o dodatkow\u0105 metod\u0119 przekazuj\u0105c ten obiekt poprzedzaj\u0105c go s\u0142owem <em><strong>this<\/strong><\/em>. Nale\u017cy pami\u0119ta\u0107, \u017ce taka metoda musi by\u0107 statyczna.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static string AddIntScore(this string str, int parameter)\r\n{\r\n    return str + &quot;: &quot; + parameter.ToString();\r\n}\r\n<\/pre>\n<p>Rezultat b\u0119dzie identyczny:<br \/>\nScore: 5<\/p>\n<h3>2. Metoda generyczna<\/h3>\n<p>Za\u0142\u00f3\u017cmy, \u017ce chcieliby\u015bmy przekazywa\u0107 parametry r\u00f3\u017cnego typu w naszej funkcji wypisuj\u0105cej ocen\u0119 ucznia. Czy aby przekaza\u0107 tym razem typ double musimy pisa\u0107 bli\u017aniacz\u0105 metod\u0119 r\u00f3\u017cni\u0105c\u0105 si\u0119 tylko jednym s\u0142owem? Na pomoc przychodz\u0105 typy <strong>generyczne<\/strong>. W definicji metody zamiast nazwy typu (tutaj int) mo\u017cemy wprowadzi\u0107 niezdefiniowany na razie typ wymieniony po nazwie metody w uko\u015bnych nawiasach. Najcz\u0119\u015bciej do okre\u015blenia typu generycznego u\u017cywamy nazwy T. P\u00f3\u017aniej zobaczymy, \u017ce r\u00f3wnie cz\u0119sto wyst\u0119puj\u0105 nazwy TInput lub TResult. Zmie\u0144my zatem metod\u0119 <em>AddIntScore<\/em> na bardziej uniwersaln\u0105.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static string AddGenericScore&lt;T&gt;(this string str, T parameter)\r\n{\r\n    return str + &quot;: &quot; + parameter.ToString();\r\n} \r\n<\/pre>\n<p>Teraz mo\u017cemy j\u0105 wywo\u0142a\u0107 zar\u00f3wno z parametrem typu int jak i np. double chc\u0105c wypisa\u0107 tym razem \u015bredni\u0105 ucznia ze wszystkich przedmiot\u00f3w. Zauwa\u017cmy, \u017ce przy wywo\u0142aniu metody mo\u017cemy ale nie musimy narzuci\u0107 metodzie typ, z kt\u00f3rego b\u0119dzie korzysta\u0142a wypisuj\u0105c go po nazwie metody w nawiasach uko\u015bnych.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nresult = s.AddGenericScore(5);  \r\nresult = s.AddGenericScore(5.3);\r\nresult = s.AddGenericScore&lt;double&gt;(5.3);\r\n<\/pre>\n<p>Otrzymany wynik to kolejno:<br \/>\nScore: 5<br \/>\nScore: 5.3<br \/>\nScore: 5.3<\/p>\n<h3>3. Delegat typu <em>Func<\/em><\/h3>\n<p>Teraz chcieliby\u015bmy wypisa\u0107 list\u0119 pi\u0119ciu ocen naszego ucznia z ostatniego miesi\u0105ca. Mamy dost\u0119pn\u0105 tablic\u0119 nazw wynik\u00f3w <em>names<\/em> oraz tablic\u0119 wynik\u00f3w <em>scores<\/em>. Ka\u017cdej nazwie odpowiada kolejno wynik zapisany w tablicy typu int.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nstring&#x5B;] names = new string&#x5B;5] { &quot;Score 1&quot;, &quot;Score 2&quot;, &quot;Score 3&quot;, &quot;Score 4&quot;, &quot;Score 5&quot; };\r\nint&#x5B;] scores = new int&#x5B;5] { 2, 4, 5, 1, 3 };\r\nstring&#x5B;] results = new string&#x5B;5];\r\n<\/pre>\n<p>Aby przeprowadzi\u0107 tak\u0105 operacj\u0119 dla pojedynczego elementu z tablicy names wystarczy\u0142aby funkcja<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nstring AddFunc(string str, int i)\r\n{\r\n   return str + &quot;: &quot; + scores&#x5B;i].ToString();\r\n}\r\n<\/pre>\n<p>Przeka\u017cmy zatem t\u0119 funkcj\u0119 jako delegat metodzie <em>AddGenericScore<\/em><\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nresults = names.AddGenericScore(AddFunc);\r\n<\/pre>\n<p>Jak przyj\u0105\u0107 taki delegat? Trzeba go samemu zdefiniowa\u0107? W wielu przypadkach nie musimy ju\u017c tego robi\u0107, gdy\u017c mamy do dyspozycji specjaln\u0105 delegacj\u0119 Func okre\u015blon\u0105 w przestrzeni nazw <em>System<\/em>. Mo\u017ce przyjmowa\u0107 od 0 do 16 parametr\u00f3w wej\u015bciowych i zawsze zwraca jeden obiekt. Widzimy poni\u017cej jedn\u0105 z jej definicji (2 parametry wej\u015bciowe T1 i T2, zwraca obiekt typu TResult). A wi\u0119c zn\u00f3w mamy typy generyczne co pozwala nam cz\u0119sto u\u017cywa\u0107 tego delegatu.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic delegate TResult Func&lt;in T1, in T2, out TResult&gt;(\r\n\tT1 arg1,\r\n\tT2 arg2\r\n)\r\n<\/pre>\n<p>Metoda realizuj\u0105ca nasze zadanie wygl\u0105da nast\u0119puj\u0105co:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static TResult&#x5B;] AddGenericScore&lt;TInput, TResult&gt;(this TInput&#x5B;] input, Func&lt;TInput, int, TResult&gt; func)\r\n{\r\n    TResult&#x5B;] result = new TResult&#x5B;input.Length];\r\n    for (int i = 0; i &lt; input.Length; i++)\r\n        result&#x5B;i] = func(input&#x5B;i], i);\r\n    return result;\r\n}\r\n<\/pre>\n<p>Metoda zwraca nam tym razem r\u00f3wnie\u017c typ generyczny TResult, co wi\u0119cej jest to tablica tego w\u0142a\u015bnie typu. Skoro doszed\u0142 nam ten typ, musimy go dopisa\u0107 w nawiasach <> po nazwie metody. Id\u017amy dalej: przyjmujemy tablic\u0119 this TInput[]  &#8211; czyli jest to metoda rozszerzona dla typu TInput[] &#8211; to ju\u017c by\u0142o. Pod koniec sygnatury metody jest wreszcie nasz delegat <em>Func<\/em>. Przyjmuje TInput oraz int a zwraca TResult.<br \/>\nW naszym zastosowaniu TInput jak i TResult b\u0119dzie stringiem. Dopisuj\u0105c cia\u0142o metody &#8211; ma\u0142\u0105 p\u0119tl\u0119 po elementach tablicy input otrzymujemy wynik:<br \/>\nScore 1: 2<br \/>\nScore 2: 4<br \/>\nScore 3: 5<br \/>\nScore 4: 1<br \/>\nScore 5: 3<\/p>\n<p>Dla potwierdzenia generyczno\u015bci tego rozwi\u0105zania wywo\u0142ajmy tym razem metod\u0119 <em>AddGenericScore<\/em> z TInput jako double i TResult jako string. Zgodnie z definicj\u0105 metoda Func b\u0119dzie w takim razie przyjmowa\u0142a kolejno: double i int a odpowiada\u0142a stringiem. Mo\u017cemy sobie wyobrazi\u0107 przyk\u0142ad, w kt\u00f3rym chcemy wypisa\u0107 te same oceny ale pomno\u017cone przez wagi typu double:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\ndouble&#x5B;] weights = new double&#x5B;5] { 2.3, 4.5, 5.4, 1.3, 3.1 };\r\n<\/pre>\n<p>Zdefiniujmy now\u0105 funkcj\u0119, kt\u00f3ra b\u0119dzie przekazana jako delegat<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nstring AddFunc2(double num, int i)\r\n{\r\n    return (num * integers&#x5B;i]).ToString();\r\n}\r\n<\/pre>\n<p>Teraz wywo\u0142anie:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n results = doubles.AddGenericScore(AddFunc2);\r\n<\/pre>\n<p>W tablicy results znajd\u0105 si\u0119 liczby reprezentowane przez typ string odpowiednio: 4.6, 18, 27, 1.3, 9.3<\/p>\n<h3>4. Func przekazywany wyra\u017ceniem lambda<\/h3>\n<p>Metod\u0119 Func mo\u017cemy r\u00f3wnie dobrze przekaza\u0107 u\u017cywaj\u0105c wyra\u017cenia lambda. Jest ona w naszym przypadku bardzo prosta, wi\u0119c czemu by jej od razu nie zdefiniowa\u0107 wywo\u0142uj\u0105c <em>AddGenericScore<\/em>. U\u017cywaj\u0105c pierwszego przyk\u0142adu (wypisanie kolejno ocen typu int) mo\u017cemy zatem j\u0105 wywo\u0142a\u0107 tak:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nresults = names.AddGenericScore((x, i) =&gt; x + &quot;: &quot; + scores&#x5B;i]);\r\n<\/pre>\n<p>Doszli\u015bmy do identycznej metody i jej wywo\u0142ania jak tej wymienionej na pocz\u0105tku postu. Przeznaczenie jest troch\u0119 inne, lecz mechanizm taki sam. Poszczeg\u00f3lne etapy budowania tej konstrukcji, komplikowanie jej krok po kroku u\u0142atwi\u0142o mi jej zrozumienie. Je\u015bli chcecie &#8220;p\u00f3j\u015b\u0107 t\u0105 drog\u0105&#8221; \ud83d\ude42 zach\u0119cam do zabawy z realnym kodem w \u015brodowisku, kompilator b\u0142yskawicznie wychwyci wszystkie b\u0142\u0119dy, kt\u00f3re gdzie\u015b tam si\u0119 mog\u0105 czai\u0107. Ca\u0142y kod z powy\u017cej przedstawionymi testami znajdziecie <a href=\"https:\/\/gist.github.com\/tomaszkacmajor\/f685238a3f0ec57355d8e9a78c0fc032\" target=\"_blank\">tutaj<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Przyjrzymy si\u0119 dzi\u015b metodzie, kt\u00f3ra widnieje na tytu\u0142owym obrazku. Szybki rzut oka: przecie\u017c nic skomplikowanego &#8211; zaledwie par\u0119 linijek kodu. Na pewno jest generyczna, bo wsz\u0119dzie tylko typy: TInput, TResult&#8230; Mimo wszystko troch\u0119 mi zaj\u0119\u0142o, \u017ceby j\u0105 zrozumie\u0107 i efektywnie z niej korzysta\u0107. Poniewa\u017c bardzo rzadko sam tworz\u0119 takie metody, postanowi\u0142em rozbi\u0107 j\u0105 na czynniki [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":360,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[9,13,12,11,16],"class_list":["post-349","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-flover-project","tag-accord-net","tag-c","tag-daj-sie-poznac","tag-flover","tag-generics-types"],"blocksy_meta":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Generyczny MegaMix - tomaszkacmajor.pl<\/title>\n<meta name=\"description\" content=\"Opis metody, kt\u00f3ra jest jednocze\u015bnie rozszerzaj\u0105ca, generyczna i przyjmuj\u0105ca generyczny delegat typu Func jako wyra\u017cenie lambda.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Generyczny MegaMix - tomaszkacmajor.pl\" \/>\n<meta property=\"og:description\" content=\"Opis metody, kt\u00f3ra jest jednocze\u015bnie rozszerzaj\u0105ca, generyczna i przyjmuj\u0105ca generyczny delegat typu Func jako wyra\u017cenie lambda.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/\" \/>\n<meta property=\"og:site_name\" content=\"tomaszkacmajor.pl\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/ProggBlogg\/\" \/>\n<meta property=\"article:published_time\" content=\"2016-04-10T19:00:09+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2016-04-30T16:12:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/tomaszkacmajor.pl\/wp-content\/uploads\/2016\/04\/Generyczny_Megamix_Head3.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1426\" \/>\n\t<meta property=\"og:image:height\" content=\"694\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"tomasz.kacmajor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@tkacmajor\" \/>\n<meta name=\"twitter:site\" content=\"@tkacmajor\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"tomasz.kacmajor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/\",\"url\":\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/\",\"name\":\"Generyczny MegaMix - tomaszkacmajor.pl\",\"isPartOf\":{\"@id\":\"https:\/\/tomaszkacmajor.pl\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/tomaszkacmajor.pl\/wp-content\/uploads\/2016\/04\/Generyczny_Megamix_Head3.png\",\"datePublished\":\"2016-04-10T19:00:09+00:00\",\"dateModified\":\"2016-04-30T16:12:12+00:00\",\"author\":{\"@id\":\"https:\/\/tomaszkacmajor.pl\/#\/schema\/person\/5f40890309a32ae4f63fa6a284215b6c\"},\"description\":\"Opis metody, kt\u00f3ra jest jednocze\u015bnie rozszerzaj\u0105ca, generyczna i przyjmuj\u0105ca generyczny delegat typu Func jako wyra\u017cenie lambda.\",\"breadcrumb\":{\"@id\":\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#primaryimage\",\"url\":\"https:\/\/tomaszkacmajor.pl\/wp-content\/uploads\/2016\/04\/Generyczny_Megamix_Head3.png\",\"contentUrl\":\"https:\/\/tomaszkacmajor.pl\/wp-content\/uploads\/2016\/04\/Generyczny_Megamix_Head3.png\",\"width\":1426,\"height\":694},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Strona g\u0142\u00f3wna\",\"item\":\"https:\/\/tomaszkacmajor.pl\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Generyczny MegaMix\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/tomaszkacmajor.pl\/#website\",\"url\":\"https:\/\/tomaszkacmajor.pl\/\",\"name\":\"tomaszkacmajor.pl\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/tomaszkacmajor.pl\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/tomaszkacmajor.pl\/#\/schema\/person\/5f40890309a32ae4f63fa6a284215b6c\",\"name\":\"tomasz.kacmajor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/tomaszkacmajor.pl\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a1fe5c8a80549b9a680c7a6f9ea33a94?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a1fe5c8a80549b9a680c7a6f9ea33a94?s=96&d=mm&r=g\",\"caption\":\"tomasz.kacmajor\"},\"url\":\"https:\/\/tomaszkacmajor.pl\/index.php\/author\/tomasz-kacmajor\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Generyczny MegaMix - tomaszkacmajor.pl","description":"Opis metody, kt\u00f3ra jest jednocze\u015bnie rozszerzaj\u0105ca, generyczna i przyjmuj\u0105ca generyczny delegat typu Func jako wyra\u017cenie lambda.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/","og_locale":"en_US","og_type":"article","og_title":"Generyczny MegaMix - tomaszkacmajor.pl","og_description":"Opis metody, kt\u00f3ra jest jednocze\u015bnie rozszerzaj\u0105ca, generyczna i przyjmuj\u0105ca generyczny delegat typu Func jako wyra\u017cenie lambda.","og_url":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/","og_site_name":"tomaszkacmajor.pl","article_publisher":"https:\/\/www.facebook.com\/ProggBlogg\/","article_published_time":"2016-04-10T19:00:09+00:00","article_modified_time":"2016-04-30T16:12:12+00:00","og_image":[{"width":1426,"height":694,"url":"https:\/\/tomaszkacmajor.pl\/wp-content\/uploads\/2016\/04\/Generyczny_Megamix_Head3.png","type":"image\/png"}],"author":"tomasz.kacmajor","twitter_card":"summary_large_image","twitter_creator":"@tkacmajor","twitter_site":"@tkacmajor","twitter_misc":{"Written by":"tomasz.kacmajor","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/","url":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/","name":"Generyczny MegaMix - tomaszkacmajor.pl","isPartOf":{"@id":"https:\/\/tomaszkacmajor.pl\/#website"},"primaryImageOfPage":{"@id":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#primaryimage"},"image":{"@id":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#primaryimage"},"thumbnailUrl":"https:\/\/tomaszkacmajor.pl\/wp-content\/uploads\/2016\/04\/Generyczny_Megamix_Head3.png","datePublished":"2016-04-10T19:00:09+00:00","dateModified":"2016-04-30T16:12:12+00:00","author":{"@id":"https:\/\/tomaszkacmajor.pl\/#\/schema\/person\/5f40890309a32ae4f63fa6a284215b6c"},"description":"Opis metody, kt\u00f3ra jest jednocze\u015bnie rozszerzaj\u0105ca, generyczna i przyjmuj\u0105ca generyczny delegat typu Func jako wyra\u017cenie lambda.","breadcrumb":{"@id":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#primaryimage","url":"https:\/\/tomaszkacmajor.pl\/wp-content\/uploads\/2016\/04\/Generyczny_Megamix_Head3.png","contentUrl":"https:\/\/tomaszkacmajor.pl\/wp-content\/uploads\/2016\/04\/Generyczny_Megamix_Head3.png","width":1426,"height":694},{"@type":"BreadcrumbList","@id":"https:\/\/tomaszkacmajor.pl\/index.php\/2016\/04\/10\/generyczny-megamix\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Strona g\u0142\u00f3wna","item":"https:\/\/tomaszkacmajor.pl\/"},{"@type":"ListItem","position":2,"name":"Generyczny MegaMix"}]},{"@type":"WebSite","@id":"https:\/\/tomaszkacmajor.pl\/#website","url":"https:\/\/tomaszkacmajor.pl\/","name":"tomaszkacmajor.pl","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/tomaszkacmajor.pl\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/tomaszkacmajor.pl\/#\/schema\/person\/5f40890309a32ae4f63fa6a284215b6c","name":"tomasz.kacmajor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/tomaszkacmajor.pl\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a1fe5c8a80549b9a680c7a6f9ea33a94?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a1fe5c8a80549b9a680c7a6f9ea33a94?s=96&d=mm&r=g","caption":"tomasz.kacmajor"},"url":"https:\/\/tomaszkacmajor.pl\/index.php\/author\/tomasz-kacmajor\/"}]}},"_links":{"self":[{"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/posts\/349","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/comments?post=349"}],"version-history":[{"count":51,"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/posts\/349\/revisions"}],"predecessor-version":[{"id":414,"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/posts\/349\/revisions\/414"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/media\/360"}],"wp:attachment":[{"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/media?parent=349"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/categories?post=349"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tomaszkacmajor.pl\/index.php\/wp-json\/wp\/v2\/tags?post=349"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}