Можа быць Там Прыватныя метады пашырэння?

Скажам, у мяне ёсць патрэба ў простым прыватным дапаможнага метаду, і інтуітыўна ў кодзе будзе мець сэнс у якасці метаду пашырэння. Ці ёсць спосаб інкапсуляцыі, што памочніца адзіны клас, які на самай справе трэба выкарыстоўваць яго?

Напрыклад, я імкнуся гэта:

class Program
{
    static void Main(string[] args)
    {
        var value = 0;
        value = value.GetNext();//Compiler error
    }

    static int GetNext(this int i)
    {
        return i + 1;
    }
}

Кампілятар не «бачыць» GetNext() метад пашырэння. памылка:

<�Р> метад пашырэння павінен быць вызначаны ў несупольнага статычны клас </р>

Справядліва, так што я абгарніце яго ў сваім класе, але ўсё-ткі заключаны ўнутры аб'екта, дзе яна належыць:

class Program
{
    static void Main(string[] args)
    {
        var value = 0;
        value = value.GetNext();//Compiler error
    }

    static class Extensions
    {
        static int GetNext(this int i)
        {
            return i + 1;
        }
    }
}

Усё яшчэ не косткі. Цяпер памылка абвяшчае:

<�Р> метад пашырэння павінен быць вызначаны ў статычным класе верхняга ўзроўню; Пашырэння з'яўляецца укладзеным класам.

Ёсць важкія прычыны для гэтага патрабавання? Ёсць выпадкі, калі дапаможны метад сапраўды павінен быць у прыватным парадку, інкапсуляваць, і ёсць выпадкі, калі код нашмат чысты і больш зручны для чытання/памяркоўны, калі дапаможны метад з'яўляецца метадам пашырэння. Для выпадкаў, калі гэтыя два перасякаюцца, абодва могуць быць задаволеныя, ці мы павінны выбраць адзін над іншым?

33
@AlexeiLevenkov: Вы, напэўна, маюць рацыю, і ў большасці выпадкаў я скончыў з толькі што выпадкова ў адзіночку. Здавалася б, што большасць маіх «прыватных» памочнікаў у адведзеных (залежнасці ўпырску) зборках вантробы якіх нават не бачныя на астатнюю частцы дамена, і гэта было проста лёгка зрабіць пашырэнне верхняга ўзроўню ў той выпадак. Толькі нядаўна гэта прыдумалі.
дададзена аўтар David, крыніца
@AlexeiLevenkov: Вы, напэўна, маюць рацыю, і ў большасці выпадкаў я скончыў з толькі што выпадкова ў адзіночку. Здавалася б, што большасць маіх «прыватных» памочнікаў у адведзеных (залежнасці ўпырску) зборках вантробы якіх нават не бачныя на астатнюю частцы дамена, і гэта было проста лёгка зрабіць пашырэнне верхняга ўзроўню ў той выпадак. Толькі нядаўна гэта прыдумалі.
дададзена аўтар David, крыніца
@ Bearcat9425: Цікава, што робіць працу. Аднак, што калі клас у пытанні не з'яўляецца статычным? У надуманы прыклад гэта досыць лёгка зрабіць яго статычным, але ў мадэлі прадметнай вобласці не так шмат.
дададзена аўтар David, крыніца
@ Bearcat9425: Цікава, што робіць працу. Аднак, што калі клас у пытанні не з'яўляецца статычным? У надуманы прыклад гэта досыць лёгка зрабіць яго статычным, але ў мадэлі прадметнай вобласці не так шмат.
дададзена аўтар David, крыніца
@ Bearcat9425, што б * фікс »гэты канкрэтны сцэнар выпадкі выкарыстання, але не быць наогул прымяняецца. Я мяркую, гэтае пытанне для агульнага прымянення, а не для узораў кансольных прыкладанняў.
дададзена аўтар Anthony Pegram, крыніца
@ Bearcat9425, што б * фікс »гэты канкрэтны сцэнар выпадкі выкарыстання, але не быць наогул прымяняецца. Я мяркую, гэтае пытанне для агульнага прымянення, а не для узораў кансольных прыкладанняў.
дададзена аўтар Anthony Pegram, крыніца
Я падазраю, што лепшае, што вы можаце атрымаць ўнутраны/ўнутраны метад пашырэння статычнага класа і схаваць яго ў нейкіх незразумелых імёнах ...
дададзена аўтар Alexei Levenkov, крыніца
Я падазраю, што лепшае, што вы можаце атрымаць ўнутраны/ўнутраны метад пашырэння статычнага класа і схаваць яго ў нейкіх незразумелых імёнах ...
дададзена аўтар Alexei Levenkov, крыніца
Прачытайце тое, што першае Паведамленне пра памылку казала, яго жаданне вам праграма класа статычнага, Спрабавалі Ці вы зрабіць яго статычным і які спрабуе код?
дададзена аўтар Bearcat9425, крыніца
Прачытайце тое, што першае Паведамленне пра памылку казала, яго жаданне вам праграма класа статычнага, Спрабавалі Ці вы зрабіць яго статычным і які спрабуе код?
дададзена аўтар Bearcat9425, крыніца
Звязаны пытанне:
дададзена аўтар cvraman, крыніца
Звязаны пытанне:
дададзена аўтар cvraman, крыніца

9 адказы

<�Р> Ёсць важкія прычыны для гэтага патрабавання?

Гэта няправільны пытанне. Пытанне зададзены праектная каманда мовы, калі мы распрацоўвалі гэтую асаблівасць была:

<�Р> Ёсць важкія прычыны, каб метады пашырэння павінны быць абвешчаныя ва ўкладзеных статычных тыпах?

Паколькі метады пашырэння былі распрацаваны, каб зрабіць працу LINQ і LINQ не мае сцэнарыяў, у якіх метаду пашырэньні было б прыватнай да тыпу, адказ быў «няма, няма такіх важкіх прычын».

Выключыўшы магчымасць паставіць метады пашырэння ў статычных ўкладзеных тыпах, ні адзін з правілаў для пошуку метадаў пашырэння ў статычных ўкладзеных тыпах, неабходных, каб быць хоць, спрачаліся пра тое, распрацавана, вызначана, рэалізавана, выпрабаванае, задакументавана, адгружаных спажывец, або <�моцны> зробленыя сумяшчальнымі з кожнай будучай асаблівасцю C# . Гэта істотная эканомія выдаткаў.

37
дададзена
Тэарэтычна гэта правільны адказ. Праектная група павінна ўсталяваць межы да таго, што код можа зрабіць, каб зрабіць яго кіраваным.
дададзена аўтар DerpyNerd, крыніца
<�Код> «шукае метады пашырэння» - Там тая частка, я не думаў пра тое, прама там. Гэта досыць проста крычаць з-за трыбуны, што "гэта павінна працаваць», забываючы высілак, неабходнае, каб зрабіць яго працу. Цалкам мае сэнс цяпер, і ў спалучэнні з адказам Аляксея прыходзіць на вельмі працаздольным рашэнне. Дзякуй!
дададзена аўтар David, крыніца
Тое, што гэта гаворыць мне, што час распрацоўкі сапраўды не распрацоўваць метады пашырэння самі па сабе, яны прызначаны LINQ. Выпадкі выкарыстання для метадаў пашырэння быць прыватнымі з'яўляюцца аднолькавымі для ўсё іншага спосабу з'яўляецца прыватным. Там няма нічога асаблівага пра метады пашырэння.
дададзена аўтар Puppy, крыніца
Я думаю, што гэта лепшы адказ. Тым не менш, я спадзяюся, што з спрытам Рослин, гэта можа быць, калі-небудзь перагледжана, у прыватнасці, для лакальных функцый. Метады пашырэння вырашаюць больш, чым проста LINQ - яны дазваляюць «свабодна» самодокументирован абвязкі дадзеных такім чынам, што традыцыйныя выклікі функцыі не робяць. Я б асабіста, як лямбда тыпу-inferenced і выраз лямбда ... мала выразнага codelets мясцовых ў вобласці. C# каманда кажа, што мясцовыя функцыі абранай альтэрнатывы тыпу-inferenced лямбда (дэлегат двухсэнсоўнасць і г.д.), так вось мой голас за інвестыцыі ў прыслабіўшы гэта абмежаванне.
дададзена аўтар David Cuccia, крыніца
<�Р> Ёсць важкія прычыны для гэтага патрабавання?

Гэта няправільны пытанне. Пытанне зададзены праектная каманда мовы, калі мы распрацоўвалі гэтую асаблівасць была:

<�Р> Ёсць важкія прычыны, каб метады пашырэння павінны быць абвешчаныя ва ўкладзеных статычных тыпах?

Паколькі метады пашырэння былі распрацаваны, каб зрабіць працу LINQ і LINQ не мае сцэнарыяў, у якіх метаду пашырэньні было б прыватнай да тыпу, адказ быў «няма, няма такіх важкіх прычын».

Выключыўшы магчымасць паставіць метады пашырэння ў статычных ўкладзеных тыпах, ні адзін з правілаў для пошуку метадаў пашырэння ў статычных ўкладзеных тыпах, неабходных, каб быць хоць, спрачаліся пра тое, распрацавана, вызначана, рэалізавана, выпрабаванае, задакументавана, адгружаных спажывец, або <�моцны> зробленыя сумяшчальнымі з кожнай будучай асаблівасцю C# . Гэта істотная эканомія выдаткаў.

37
дададзена
Тэарэтычна гэта правільны адказ. Праектная група павінна ўсталяваць межы да таго, што код можа зрабіць, каб зрабіць яго кіраваным.
дададзена аўтар DerpyNerd, крыніца
<�Код> «шукае метады пашырэння» - Там тая частка, я не думаў пра тое, прама там. Гэта досыць проста крычаць з-за трыбуны, што "гэта павінна працаваць», забываючы высілак, неабходнае, каб зрабіць яго працу. Цалкам мае сэнс цяпер, і ў спалучэнні з адказам Аляксея прыходзіць на вельмі працаздольным рашэнне. Дзякуй!
дададзена аўтар David, крыніца
Тое, што гэта гаворыць мне, што час распрацоўкі сапраўды не распрацоўваць метады пашырэння самі па сабе, яны прызначаны LINQ. Выпадкі выкарыстання для метадаў пашырэння быць прыватнымі з'яўляюцца аднолькавымі для ўсё іншага спосабу з'яўляецца прыватным. Там няма нічога асаблівага пра метады пашырэння.
дададзена аўтар Puppy, крыніца
Я думаю, што гэта лепшы адказ. Тым не менш, я спадзяюся, што з спрытам Рослин, гэта можа быць, калі-небудзь перагледжана, у прыватнасці, для лакальных функцый. Метады пашырэння вырашаюць больш, чым проста LINQ - яны дазваляюць «свабодна» самодокументирован абвязкі дадзеных такім чынам, што традыцыйныя выклікі функцыі не робяць. Я б асабіста, як лямбда тыпу-inferenced і выраз лямбда ... мала выразнага codelets мясцовых ў вобласці. C# каманда кажа, што мясцовыя функцыі абранай альтэрнатывы тыпу-inferenced лямбда (дэлегат двухсэнсоўнасць і г.д.), так вось мой голас за інвестыцыі ў прыслабіўшы гэта абмежаванне.
дададзена аўтар David Cuccia, крыніца

Я лічу, што лепшае, што вы можаце атрымаць у агульным выпадку ўнутраны статычны клас з метадамі ўнутраны статычнымі пашырэння. Так як гэта будзе ў вашай ўласнай зборкі толькі людзі, вам трэба, каб прадухіліць выкарыстанне пашырэння з'яўляюцца аўтарамі зборкі - так што некаторыя відавочна названы прасторы імёнаў (напрыклад, My.Extensions.ForFoobarOnly ) можа быць дастаткова, каб намякнуць каб пазбегнуць злоўжыванняў.

Мінімальны ўнутраны абмежаванне разглядаецца ў ажыццявіць пашырэнне </а> артыкул

<�Р> Клас павінен быць бачны код кліента ... метад, па меншай меры, такі ж, як бачнасць які змяшчае класа.

Заўвага: Я хацеў бы зрабіць пашырэнне грамадскага ў любым выпадку для спрашчэння модульнага тэставання, але пакласці ў некаторых відавочна з імем прасторы імёнаў, як Xxxx.Yyyy.Internal , так што іншыя карыстальнікі зборкі не чакалі б метадаў, якія будуць падтрымлівацца/выкліканымі. Па сутнасці спадзявацца на канвенцыі, акрамя кампіляцыі выканання часу.

15
дададзена
Я, верагодна, будзе гуляць з канвенцыямі на працягу доўгага часу, каб прыйсці, у рэшце рэшт, які прыбываў на тое, што мае сэнс. Гэта досыць рэдкі выпадак, калі я не вельмі хвалююся, гэта проста пытанне аб выхадзе з кодавую ў інтуітыўнай і падтрымоўваным стане для таго, хто павінен падтрымліваць яго ў будучыні (у тым ліку і я). Дзякуй!
дададзена аўтар David, крыніца
@Przemo InternalsVisibleToAttribute сапраўды можа быць выкарыстаны, але ён забівае некаторыя юзабіліці метады пашырэння, паколькі яны больш не будуць адлюстроўвацца ў аўтазапаўнення, наколькі я ведаю. Гэта больш-менш асабісты выбар для большасці праектаў (за выключэннем некаторых бібліятэк, прызначаныя для вельмі шырокага выкарыстання) - вы павінны важыць зручнасць супраць чысціні API ў вашым канкрэтным выпадку. Праекты Працуюць у цэлым «маленькае» і не падвяргаючы сапраўднае грамадскае API, - так грамадскасці выдатна працуе ў маім выпадку.
дададзена аўтар Alexei Levenkov, крыніца
Аляксей: калі гэта толькі для модульнага тэставання, не было б лепш пакінуць пашырэнне унутраным і выкрыць вантробы на тэстах праект з выкарыстаннем InternalsVisibleToAttribute ( msdn.microsoft.com/en-us/library/… )?
дададзена аўтар Przemo, крыніца

Я лічу, што лепшае, што вы можаце атрымаць у агульным выпадку ўнутраны статычны клас з метадамі ўнутраны статычнымі пашырэння. Так як гэта будзе ў вашай ўласнай зборкі толькі людзі, вам трэба, каб прадухіліць выкарыстанне пашырэння з'яўляюцца аўтарамі зборкі - так што некаторыя відавочна названы прасторы імёнаў (напрыклад, My.Extensions.ForFoobarOnly ) можа быць дастаткова, каб намякнуць каб пазбегнуць злоўжыванняў.

Мінімальны ўнутраны абмежаванне разглядаецца ў ажыццявіць пашырэнне </а> артыкул

<�Р> Клас павінен быць бачны код кліента ... метад, па меншай меры, такі ж, як бачнасць які змяшчае класа.

Заўвага: Я хацеў бы зрабіць пашырэнне грамадскага ў любым выпадку для спрашчэння модульнага тэставання, але пакласці ў некаторых відавочна з імем прасторы імёнаў, як Xxxx.Yyyy.Internal , так што іншыя карыстальнікі зборкі не чакалі б метадаў, якія будуць падтрымлівацца/выкліканымі. Па сутнасці спадзявацца на канвенцыі, акрамя кампіляцыі выканання часу.

15
дададзена
Я, верагодна, будзе гуляць з канвенцыямі на працягу доўгага часу, каб прыйсці, у рэшце рэшт, які прыбываў на тое, што мае сэнс. Гэта досыць рэдкі выпадак, калі я не вельмі хвалююся, гэта проста пытанне аб выхадзе з кодавую ў інтуітыўнай і падтрымоўваным стане для таго, хто павінен падтрымліваць яго ў будучыні (у тым ліку і я). Дзякуй!
дададзена аўтар David, крыніца
@Przemo InternalsVisibleToAttribute сапраўды можа быць выкарыстаны, але ён забівае некаторыя юзабіліці метады пашырэння, паколькі яны больш не будуць адлюстроўвацца ў аўтазапаўнення, наколькі я ведаю. Гэта больш-менш асабісты выбар для большасці праектаў (за выключэннем некаторых бібліятэк, прызначаныя для вельмі шырокага выкарыстання) - вы павінны важыць зручнасць супраць чысціні API ў вашым канкрэтным выпадку. Праекты Працуюць у цэлым «маленькае» і не падвяргаючы сапраўднае грамадскае API, - так грамадскасці выдатна працуе ў маім выпадку.
дададзена аўтар Alexei Levenkov, крыніца
Аляксей: калі гэта толькі для модульнага тэставання, не было б лепш пакінуць пашырэнне унутраным і выкрыць вантробы на тэстах праект з выкарыстаннем InternalsVisibleToAttribute ( msdn.microsoft.com/en-us/library/… )?
дададзена аўтар Przemo, крыніца

Гэты код кампілюецца і працуе:

static class Program
{
    static void Main(string[] args)
    {
        var value = 0;
        value = value.GetNext();//Compiler error
    }

    static int GetNext(this int i)
    {
        return i + 1;
    }
}

Звярніце ўвагу на Праграма статычнага класа лініі, якая была тое, што сказаў кампілятар патрэбны.

1
дададзена
Я не ў курсе вашых даменаў вантроб і, хутчэй за ўсё, вы маеце рацыю. Аднак, калі яны з'яўляюцца толькі некаторымі дапаможнымі функцыямі, то, магчыма, яны не павінны быць метадамі пашырэння. Метады пашырэння прызначаныя для забеспячэння статычны тыпізаваных формы качынага тыпізацыі, якая ў сваёй чаргі, была неабходна для рэалізацыі нейкага сістэм вышэйшай тыпу парадку, неабходных для такіх рэчаў, як LINQ (манадай прывязаная да IEnumerable ). Яны не маюць нічога агульнага з інкапсуляцыі. Аднак (ізноў жа), вы можаце фармаваць яго на волю. Так што «перадавая практыка» частка была тое, што я сам даведаўся ад іншых, і на практыцы дапамог мне; і гэта сваяк!
дададзена аўтар Kaveh Shahbazian, крыніца
Вось чаму яны называюцца «Метаду пашырэння» і лепшая практыка, каб вызначыць іх у асобным статычным класе, змешчаным пад іншым прасторы імёнаў.
дададзена аўтар Kaveh Shahbazian, крыніца
«Найлепшая практыка» з'яўляецца адносным паняццем. Інкапсуляцыя таксама лепшая практыка. Ёсць выпадкі, калі кладучы дапаможныя функцыі (у дадзеным выпадку пашырэньні метадаў) у асобны клас (ці цалкам асобнае прастору імёнаў) вынікаў у дзіравай абстракцыі, шчыльна счаплення, што дапаможныя функцыі з вантробамі адзіным аб'ектам, які ён дапамагае.
дададзена аўтар David, крыніца
Гэта выдатна працуе ў маім надуманы прыклад, я прызнаю. Але што робіць клас статычным не заўсёды з'яўляецца жыццяздольным варыянтам. Для мадэляў прадметнай вобласці гэта можа выклікаць вялікія праблемы.
дададзена аўтар David, крыніца

Гэты код кампілюецца і працуе:

static class Program
{
    static void Main(string[] args)
    {
        var value = 0;
        value = value.GetNext();//Compiler error
    }

    static int GetNext(this int i)
    {
        return i + 1;
    }
}

Звярніце ўвагу на Праграма статычнага класа лініі, якая была тое, што сказаў кампілятар патрэбны.

1
дададзена
Я не ў курсе вашых даменаў вантроб і, хутчэй за ўсё, вы маеце рацыю. Аднак, калі яны з'яўляюцца толькі некаторымі дапаможнымі функцыямі, то, магчыма, яны не павінны быць метадамі пашырэння. Метады пашырэння прызначаныя для забеспячэння статычны тыпізаваных формы качынага тыпізацыі, якая ў сваёй чаргі, была неабходна для рэалізацыі нейкага сістэм вышэйшай тыпу парадку, неабходных для такіх рэчаў, як LINQ (манадай прывязаная да IEnumerable ). Яны не маюць нічога агульнага з інкапсуляцыі. Аднак (ізноў жа), вы можаце фармаваць яго на волю. Так што «перадавая практыка» частка была тое, што я сам даведаўся ад іншых, і на практыцы дапамог мне; і гэта сваяк!
дададзена аўтар Kaveh Shahbazian, крыніца
Вось чаму яны называюцца «Метаду пашырэння» і лепшая практыка, каб вызначыць іх у асобным статычным класе, змешчаным пад іншым прасторы імёнаў.
дададзена аўтар Kaveh Shahbazian, крыніца
«Найлепшая практыка» з'яўляецца адносным паняццем. Інкапсуляцыя таксама лепшая практыка. Ёсць выпадкі, калі кладучы дапаможныя функцыі (у дадзеным выпадку пашырэньні метадаў) у асобны клас (ці цалкам асобнае прастору імёнаў) вынікаў у дзіравай абстракцыі, шчыльна счаплення, што дапаможныя функцыі з вантробамі адзіным аб'ектам, які ён дапамагае.
дададзена аўтар David, крыніца
Гэта выдатна працуе ў маім надуманы прыклад, я прызнаю. Але што робіць клас статычным не заўсёды з'яўляецца жыццяздольным варыянтам. Для мадэляў прадметнай вобласці гэта можа выклікаць вялікія праблемы.
дададзена аўтар David, крыніца

Я лічу, што гэта спосаб, якім яны рэалізавалі кампіляцыю з метадаў Extensions.

Гледзячы на ​​IL, здаецца, што яны дадаюць некаторыя дадатковыя атрыбуты да метаду.

.method public hidebysig static int32 GetNext(int32 i) cil managed
{
    .custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] int32 num)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldc.i4.1 
    L_0003: add 
    L_0004: dup 
    L_0005: starg.s i
    L_0007: stloc.0 
    L_0008: br.s L_000a
    L_000a: ldloc.0 
    L_000b: ret 
}

Існуе, верагодна, некаторыя вельмі важна, каб мы выпускаем, што толькі не робіць яго працу таму абмежаванне на месцы. Можа таксама быць, што яны хацелі прымусіць практыку кадавання. На жаль, гэта проста не працуе і павінна быць у статычных класах верхняга ўзроўню.

1
дададзена

Гэта ўзята з прыкладу на Microsoft MSDN. Метады Extesnion павінны быць вызначаны ў статычным класе. Паглядзіце, як статычны клас быў вызначаны ў іншым прасторы імёнаў і імпартаваны. Вы можаце ўбачыць прыклад тут http://msdn.microsoft.com/en-us/library/bb311042 (v = VS.90) .aspx

namespace TestingEXtensions
{
    using CustomExtensions;
    class Program
    {
        static void Main(string[] args)
        {
            var value = 0;
            Console.WriteLine(value.ToString()); //Test output
            value = value.GetNext(); 
            Console.WriteLine(value.ToString());//see that it incremented
            Console.ReadLine();
        }
    }
}

namespace CustomExtensions 
{
    public static class IntExtensions
    {
        public static int GetNext(this int i)
        {
            return i + 1;
        }
    }
}
1
дададзена

Гэта ўзята з прыкладу на Microsoft MSDN. Метады Extesnion павінны быць вызначаны ў статычным класе. Паглядзіце, як статычны клас быў вызначаны ў іншым прасторы імёнаў і імпартаваны. Вы можаце ўбачыць прыклад тут http://msdn.microsoft.com/en-us/library/bb311042 (v = VS.90) .aspx

namespace TestingEXtensions
{
    using CustomExtensions;
    class Program
    {
        static void Main(string[] args)
        {
            var value = 0;
            Console.WriteLine(value.ToString()); //Test output
            value = value.GetNext(); 
            Console.WriteLine(value.ToString());//see that it incremented
            Console.ReadLine();
        }
    }
}

namespace CustomExtensions 
{
    public static class IntExtensions
    {
        public static int GetNext(this int i)
        {
            return i + 1;
        }
    }
}
1
дададзена