'අස්වැන්න ප්‍රතිලාභ' නිසි ලෙස භාවිතා කිරීම


914

මෙම අස්වැන්න මූල පදය එම එක් ප්රධාන වචන මට mystify දිගටම බව C #, සහ මම එය නිවැරදිව භාවිතා කරනවා ඇති දැඩි විශ්වාසයයි කිසි දෙයක් කියලා නැහැ.

පහත දැක්වෙන කේත කැබලි දෙකෙන්, වඩාත් කැමති සහ ඇයි?

අනුවාදය 1: අස්වැන්න ප්‍රතිලාභ භාවිතා කිරීම

public static IEnumerable<Product> GetAllProducts()
{
    using (AdventureWorksEntities db = new AdventureWorksEntities())
    {
        var products = from product in db.Product
                       select product;

        foreach (Product product in products)
        {
            yield return product;
        }
    }
}

අනුවාදය 2: ලැයිස්තුව ආපසු එවන්න

public static IEnumerable<Product> GetAllProducts()
{
    using (AdventureWorksEntities db = new AdventureWorksEntities())
    {
        var products = from product in db.Product
                       select product;

        return products.ToList<Product>();
    }
}

38
yieldහා බැඳී ඇත IEnumerable<T>. එය කෙසේ හෝ කම්මැලි
ඇගයීමකි

මෙන්න ඒ හා සමාන ප්‍රශ්නයට විශිෂ්ට පිළිතුරකි. stackoverflow.com/questions/15381708/…
සංජීව් රායි

1
මෙන්න හොඳ භාවිත උදාහරණයක්: stackoverflow.com/questions/3392612/…
ValGe

6
yield returnප්‍රති results ල හරහා පුනරාවර්තනය වන කේතය GetAllProducts()පරිශීලකයාට අකාලයේ සැකසුම් අවලංගු කිරීමට අවස්ථාවක් ලබා දෙන්නේ නම් භාවිතා කිරීම සඳහා හොඳ අවස්ථාවක් මම දකිමි .
ජේඑම්ඩී

2
මෙම ත්‍රෙඩ් එක මට සැබවින්ම ප්‍රයෝජනවත් විය: programmmers.stackexchange.com/a/97350/148944
PiotrWolkowski

Answers:


812

මම ලැයිස්තුවේ ඊළඟ අයිතමය ගණනය කරන විට (හෝ ඊළඟ අයිතම සමූහය) අස්වැන්න-ප්‍රතිලාභ භාවිතා කිරීමට නැඹුරු වෙමි.

ඔබේ අනුවාදය 2 භාවිතා කරමින්, නැවත පැමිණීමට පෙර සම්පූර්ණ ලැයිස්තුව ඔබ සතුව තිබිය යුතුය. අස්වැන්න-ප්‍රතිලාභ භාවිතා කිරීමෙන්, ඔබට ඇත්ත වශයෙන්ම අවශ්‍ය වන්නේ නැවත පැමිණීමට පෙර ඊළඟ අයිතමය පමණි.

වෙනත් දේ අතර, මෙය සංකීර්ණ ගණනය කිරීම්වල පරිගණක පිරිවැය විශාල කාල රාමුවක් පුරා ව්‍යාප්ත කිරීමට උපකාරී වේ. උදාහරණයක් ලෙස, ලැයිස්තුව GUI එකකට සම්බන්ධ කර ඇති අතර පරිශීලකයා කිසි විටෙකත් අවසාන පිටුවට නොයන්නේ නම්, ඔබ කිසි විටෙකත් ලැයිස්තුවේ අවසාන අයිතම ගණනය නොකරයි.

IEnumerable අනන්ත කට්ටලයක් නියෝජනය කරන්නේ නම් අස්වැන්න-ප්‍රතිලාභ ලබා ගැනීම වඩාත් සුදුසු තවත් අවස්ථාවකි. ප්‍රයිම් අංක ලැයිස්තුව හෝ අහඹු සංඛ්‍යා ලැයිස්තුවක් සලකා බලන්න. ඔබට කිසි විටෙකත් සම්පූර්ණ IEnumerable එකවර ආපසු ලබා දිය නොහැක, එබැවින් ඔබ වැඩි වැඩියෙන් ලැයිස්තුව ආපසු ලබා දීමට අස්වැන්න-ප්‍රතිලාභ භාවිතා කරයි.

ඔබේ විශේෂ උදාහරණයේ, ඔබ සතුව නිෂ්පාදනවල සම්පූර්ණ ලැයිස්තුවක් ඇත, එබැවින් මම අනුවාදය 2 භාවිතා කරමි.


31
3 වන ප්‍රශ්නයේ ඔබේ උදාහරණයේ ප්‍රතිලාභ දෙකක් ඇති බව මම දනිමි. 1) එය පරිගණක පිරිවැය ව්‍යාප්ත කරයි (සමහර විට ප්‍රතිලාභයක්, සමහර විට නොවේ) 2) බොහෝ භාවිත අවස්ථා වලදී එය දින නියමයක් නොමැතිව ගණනය කිරීම වළක්වා ගත හැකිය. එය අතරමැදි තත්වය වටා ඇති විය හැකි අඩුපාඩුව සඳහන් කිරීමට ඔබ අසමත් වේ. ඔබට සැලකිය යුතු ප්‍රමාණයේ අතරමැදි තත්වයක් තිබේ නම් (අනුපිටපත් ඉවත් කිරීම සඳහා හැෂ්සෙට් එකක් කියන්න) එවිට අස්වැන්න භාවිතා කිරීමෙන් ඔබේ මතක අඩිපාර වැඩි කළ හැකිය.
කෙනට් බෙලෙන්කි

8
එසේම, එක් එක් මූලද්රව්ය ඉතා විශාල නම්, නමුත් ඒවා අනුක්රමිකව ප්රවේශ විය යුතු නම්, අස්වැන්නක් වඩා හොඳය.
කෙනට් බෙලෙන්කි

2
අවසාන වශයෙන් ... අසමමුහුර්ත කේතය ඉතා අනුක්‍රමික ස්වරූපයෙන් ලිවීමට අස්වැන්න භාවිතා කිරීම සඳහා තරමක් විස්මයජනක නමුත් ඉඳහිට effective ලදායී තාක්‍ෂණයක් ඇත.
කෙනට් බෙලෙන්කි

12
සිත්ගන්නාසුලු තවත් උදාහරණයක් නම් තරමක් විශාල CSV ගොනු කියවීමේදී ය. ඔබට එක් එක් අංග කියවීමට අවශ්‍ය නමුත් ඔබේ යැපීම උකහා ගැනීමටද ඔබට අවශ්‍යය. IEnumerable <> ආපසු ලබා දීමෙන් ඔබට එක් එක් පේළිය නැවත ලබා දීමට සහ එක් එක් පේළිය තනි තනිව සැකසීමට ඉඩ ලබා දේ. මතකයට 10 Mb ගොනුවක් කියවීමට අවශ්‍ය නැත. වරකට එක් පේළියක් පමණි.
මැක්සිම් රුවිලර්

1
Yield returnඔබේම අභිරුචි අනුකාරක පන්තියක් ලිවීම සඳහා කෙටිකාලීන බවක් පෙනේ (IEnumerator ක්‍රියාත්මක කරන්න). එබැවින්, සඳහන් ප්‍රතිලාභ අභිරුචි පුනරාවර්තන පන්ති සඳහා ද අදාළ වේ. කෙසේ වෙතත්, ඉදිකිරීම් දෙකම අතරමැදි තත්වයක් තබා ගනී. එහි වඩාත්ම සරල ස්වරූපයෙන් එය වත්මන් වස්තුව වෙත යොමු කිරීමක් වේ.
ජේ. ඕවෙහාන්ඩ්

650

තාවකාලික ලැයිස්තුවක් ජනගහනය කිරීම මුළු වීඩියෝව බාගත කිරීම yieldහා සමාන වන අතර භාවිතා කිරීම එම වීඩියෝව ප්‍රවාහය කිරීම වැනි ය.


185
මෙම පිළිතුර තාක්ෂණික පිළිතුරක් නොවන බව මම හොඳින් දනිමි, නමුත් අස්වැන්න සහ වීඩියෝ ප්‍රවාහය අතර ඇති සමානකම අස්වැන්න යතුරුපදය තේරුම් ගැනීමේදී හොඳ උදාහරණයක් ලෙස සේවය කරන බව මම විශ්වාස කරමි. මෙම විෂය පිළිබඳව තාක්‍ෂණික සෑම දෙයක්ම දැනටමත් පවසා ඇති බැවින් මම "වෙනත් වචන වලින්" පැහැදිලි කිරීමට උත්සාහ කළෙමි. තාක්‍ෂණික නොවන වචන වලින් ඔබේ අදහස් පැහැදිලි කළ නොහැකි යැයි පවසන ප්‍රජා රීතියක් තිබේද?
anar khalilov

13
ඔබට ඡන්දය දුන්නේ කවුරුන්ද යන්න හෝ ඇයි (ඔවුන් අදහස් දක්වනු ඇතැයි මම සිතමි), නමුත් එය තාක්‍ෂණික නොවන අපේක්ෂකයෙකුගෙන් එය තරමක් විස්තර කරයි යැයි මම සිතමි.
senfo

22
තවමත් සංකල්පය ග්‍රහණය කර ගෙන ඇති අතර මෙය තව දුරටත් අවධානයට යොමු කිරීමට උපකාරී විය.
ටෝනි

11
මම මෙම පිළිතුරට කැමතියි, නමුත් එය ප්‍රශ්නයට පිළිතුරු සපයන්නේ නැත.
ඇනෙව්ස් සිතන්නේ SE නපුරු යැයි

75

ඔබ භාවිතා කළ යුතු විට තේරුම් ගැනීම සඳහා සංකල්පීය උදාහරණයක් ලෙස yield, ක්‍රමය ConsumeLoop()මඟින් ආපසු ලබා දුන් / ලබා දුන් අයිතම ක්‍රියාවට නංවන ආකාරය කියමු ProduceList():

void ConsumeLoop() {
    foreach (Consumable item in ProduceList())        // might have to wait here
        item.Consume();
}

IEnumerable<Consumable> ProduceList() {
    while (KeepProducing())
        yield return ProduceExpensiveConsumable();    // expensive
}

නොමැතිව yield, ProduceList()නැවත පැමිණීමට පෙර ලැයිස්තුව සම්පූර්ණ කළ යුතු බැවින් ඇමතුම සඳහා බොහෝ කාලයක් ගතවනු ඇත:

//pseudo-assembly
Produce consumable[0]                   // expensive operation, e.g. disk I/O
Produce consumable[1]                   // waiting...
Produce consumable[2]                   // waiting...
Produce consumable[3]                   // completed the consumable list
Consume consumable[0]                   // start consuming
Consume consumable[1]
Consume consumable[2]
Consume consumable[3]

භාවිතා කිරීමෙන් yield, එය නැවත සකස් කර, අන්තර් සම්බන්ධිත ආකාරයකට පත්වේ:

//pseudo-assembly
Produce consumable[0]
Consume consumable[0]                   // immediately yield & Consume
Produce consumable[1]                   // ConsumeLoop iterates, requesting next item
Consume consumable[1]                   // consume next
Produce consumable[2]
Consume consumable[2]                   // consume next
Produce consumable[3]
Consume consumable[3]                   // consume next

අවසාන වශයෙන්, බොහෝ දෙනෙක් දැනටමත් යෝජනා කර ඇති පරිදි, ඔබ කෙසේ හෝ සම්පූර්ණ කරන ලද ලැයිස්තුව දැනටමත් ඇති බැවින් ඔබ අනුවාදය 2 භාවිතා කළ යුතුය.


30

මෙය පැරණි ප්‍රශ්නයක් බව මම දනිමි, නමුත් අස්වැන්න යතුරු පදය නිර්මාණාත්මකව භාවිතා කළ හැකි ආකාරය පිළිබඳ එක් උදාහරණයක් ඉදිරිපත් කිරීමට මම කැමැත්තෙමි. මම මෙම තාක්‍ෂණයෙන් සැබවින්ම ප්‍රයෝජන ලබා ඇත්තෙමි . මෙම ප්‍රශ්නයට බාධා කරන වෙනත් ඕනෑම කෙනෙකුට මෙය උපකාරයක් වනු ඇතැයි අපේක්‍ෂා කරමු.

සටහන: අස්වැන්න යතුරු පදය හුදෙක් එකතුවක් තැනීමේ තවත් ක්‍රමයක් ලෙස නොසිතන්න. අස්වැන්න බලයේ විශාල කොටසක් පැමිණෙන්නේ ඇමතුම් කේතය ඊළඟ අගයට වඩා පුනරාවර්තනය වන තෙක් ඔබේ ක්‍රමවේදය හෝ දේපල ක්‍රියාත්මක කිරීම නවතා දමා ඇති බැවිනි. මෙන්න මගේ උදාහරණය:

අස්වැන්න යතුර භාවිතා කිරීම (රොබ් අයිසන්බර්ග්ගේ කැලිබර්න් සමඟ. මයික්‍රෝ කෝරෝටයින් ක්‍රියාත්මක කිරීම සමඟ) මට මෙවැනි වෙබ් සේවාවක් සඳහා අසමමුහුර්ත ඇමතුමක් ප්‍රකාශ කිරීමට ඉඩ දෙයි:

public IEnumerable<IResult> HandleButtonClick() {
    yield return Show.Busy();

    var loginCall = new LoginResult(wsClient, Username, Password);
    yield return loginCall;
    this.IsLoggedIn = loginCall.Success;

    yield return Show.NotBusy();
}

මෙය කරන්නේ මගේ කාර්යබහුල ඉන්ඩිකේටරය සක්‍රිය කිරීම, මගේ වෙබ් සේවාවේ පිවිසුම් ක්‍රමය අමතන්න, මගේ IsLoggedIn ධජය ප්‍රතිලාභ අගයට සකසා, පසුව කාර්යබහුල දර්ශකය ආපසු හරවන්න.

මෙය ක්‍රියාත්මක වන ආකාරය මෙන්න: IResult සතුව ක්‍රියාත්මක කිරීමේ ක්‍රමයක් සහ සම්පූර්ණ සිදුවීමක් ඇත. කැලිබර්න්.මයික්‍රෝ හෑන්ඩ්ල්බටන් ක්ලික් () වෙත කළ ඇමතුමෙන් අයිඑන්එමුරේටරය අල්ලාගෙන එය කෝරෝටයින්.බෙජින්එක්ස්කියුට් ක්‍රමයට යොමු කරයි. BeginExecute ක්‍රමය IResults හරහා නැවත ආරම්භ කිරීම ආරම්භ කරයි. පළමු IResult ආපසු ලබා දුන් විට, HandleButtonClick () තුළ ක්‍රියාත්මක කිරීම විරාමයක් ලබා දෙන අතර BeginExecute () සම්පූර්ණ කළ සිදුවීමට සිදුවීම් හසුරුවන්නෙකු සම්බන්ධ කර ක්‍රියාත්මක කරන්න () අමතන්න. IResult.Execute () හට සමමුහුර්ත හෝ අසමමුහුර්ත කාර්යයක් කළ හැකි අතර එය අවසන් වූ විට එය අවසන් වේ.

LoginResult මේ වගේ දෙයක් පෙනේ:

public LoginResult : IResult {
    // Constructor to set private members...

    public void Execute(ActionExecutionContext context) {
        wsClient.LoginCompleted += (sender, e) => {
            this.Success = e.Result;
            Completed(this, new ResultCompletionEventArgs());
        };
        wsClient.Login(username, password);
    }

    public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
    public bool Success { get; private set; }
}

මෙවැනි දෙයක් සැකසීමට සහ සිදුවන්නේ කුමක්දැයි බැලීමට එය ක්‍රියාත්මක කිරීමට පියවර ගත හැකිය.

මෙය යමෙකුට පිටතට උපකාරී වේ යැයි සිතමු! අස්වැන්න භාවිතා කළ හැකි විවිධ ක්‍රම ගවේෂණය කිරීමෙන් මම සැබවින්ම සතුටට පත්වෙමි.


1
ඔබේ කේත නියැදිය a හෝ foreach block එකක පිටත අස්වැන්න භාවිතා කරන්නේ කෙසේද යන්න පිළිබඳ කදිම නිදසුනකි. බොහෝ උදාහරණ මඟින් අනුකාරකයක් තුළ අස්වැන්න ප්‍රතිලාභ ලැබේ. SO පිළිබඳ ප්‍රශ්නය ඇසීමට සූදානම්ව සිටියදී ඉතා ප්‍රයෝජනවත් වේ.
shellbypereira

yieldමේ ආකාරයෙන් භාවිතා කිරීම මට කිසි විටෙකත් සිදු වී නැත . එය අසින්ක් / පොරොත්තු රටාව අනුකරණය කිරීමට අලංකාර ක්‍රමයක් සේ පෙනේ (මෙය yieldඅද නැවත ලිවුවහොත් වෙනුවට භාවිතා කරනු ඇතැයි මම සිතමි ). ඔබ yieldමෙම ප්‍රශ්නයට පිළිතුරු දුන් දා සිට සී # පරිණාමය වී ඇති බැවින් මෙම නිර්මාණාත්මක භාවිතයන් වසර ගණනාවක් තිස්සේ ප්‍රතිලාභ අඩුවී ඇති බව ඔබ සොයාගෙන තිබේද ? එසේත් නැතිනම් ඔබ තවමත් නවීකරණය කරන ලද දක්ෂ භාවිත අවස්ථා සමඟ පැමිණෙමින් සිටිනවාද? එසේ නම්, අප වෙනුවෙන් තවත් සිත්ගන්නාසුලු අවස්ථාවක් බෙදා ගැනීමට ඔබ කැමතිද?
අක්රමික

27

මෙය විකාර යෝජනාවක් සේ පෙනේ, නමුත් yieldපයිතන්හි ජනක යන්ත්‍ර පිළිබඳ ඉදිරිපත් කිරීමක් කියවීමෙන් මම සී # හි මූලික පදය භාවිතා කරන්නේ කෙසේදැයි ඉගෙන ගතිමි : ඩේවිඩ් එම්. බීස්ලිගේ http://www.dabeaz.com/generator/Generator.pdf . ඉදිරිපත් කිරීම තේරුම් ගැනීමට ඔබ බොහෝ පයිතන් දැන ගැනීමට අවශ්‍ය නැත - මම එසේ නොකළෙමි. ජනක යන්ත්‍ර ක්‍රියා කරන ආකාරය පමණක් නොව ඔබ සැලකිලිමත් විය යුත්තේ ඇයිද යන්න පැහැදිලි කිරීමට එය ඉතා ප්‍රයෝජනවත් බව මට පෙනී ගියේය.


1
ඉදිරිපත් කිරීම සරල දළ විශ්ලේෂණයක් සපයයි. සී # හි එය ක්‍රියාත්මක වන ආකාරය පිළිබඳ විස්තර රේ චෙන් විසින් stackoverflow.com/a/39507/939250 හි සබැඳි මගින් සාකච්ඡා කරනු ලැබේ .
ඩොනල් ලැෆර්ටි

19

මිලියන ගණනක් වස්තූන් හරහා නැවත යෙදීමට අවශ්‍ය ඇල්ගොරිතම සඳහා අස්වැන්න ආපසු පැමිණීම ඉතා බලවත් විය හැකිය. ධාවන බෙදාගැනීම සඳහා කළ හැකි සංචාර ගණනය කිරීමට අවශ්‍ය පහත උදාහරණය සලකා බලන්න. පළමුව අපි හැකි සංචාර ජනනය කරමු:

    static IEnumerable<Trip> CreatePossibleTrips()
    {
        for (int i = 0; i < 1000000; i++)
        {
            yield return new Trip
            {
                Id = i.ToString(),
                Driver = new Driver { Id = i.ToString() }
            };
        }
    }

ඉන්පසු සෑම සංචාරයක් හරහාම නැවත කියන්න:

    static void Main(string[] args)
    {
        foreach (var trip in CreatePossibleTrips())
        {
            // possible trip is actually calculated only at this point, because of yield
            if (IsTripGood(trip))
            {
                // match good trip
            }
        }
    }

අස්වැන්න වෙනුවට ඔබ ලැයිස්තුව භාවිතා කරන්නේ නම්, ඔබට වස්තු මිලියනයක් මතකයට (mb 190mb) වෙන් කිරීමට අවශ්‍ය වන අතර මෙම සරල උදාහරණය ක්‍රියාත්මක වීමට ඩොලර් 1400 ක් ගත වේ. කෙසේ වෙතත්, ඔබ අස්වැන්නක් භාවිතා කරන්නේ නම්, ඔබට මෙම තාවකාලික වස්තු සියල්ල මතකයට දැමීමට අවශ්‍ය නොවන අතර ඔබට සැලකිය යුතු වේගයකින් ඇල්ගොරිතම වේගය ලැබෙනු ඇත: මෙම උදාහරණය කිසිදු මතක පරිභෝජනයකින් තොරව ධාවනය කිරීමට ගත වන්නේ ඩොලර් මිලියන 400 ක් පමණි.


2
ආවරණ යටතේ අස්වැන්න යනු කුමක්ද? එය ලැයිස්තුවක් යැයි මම සිතුවෙමි, එබැවින් එය මතක භාවිතය වැඩි දියුණු කරන්නේ කෙසේද?
රෝල්ස්

1
@rolls yieldරාජ්ය යන්ත්රය අභ්යන්තර ක්රියාත්මක කරමින් ආවරණ යටතේ ක්රියා කරයි. සවිස්තරාත්මක MSDN බ්ලොග් සටහන් 3 ක් සහිත SO පිළිතුරක් මෙහි ක්‍රියාත්මක කිරීම ඉතා විස්තරාත්මකව විස්තර කරයි. ලියන ලද්දේ රේමන්ඩ් චෙන් @ MSFT
ශිව

13

කේත කෑලි දෙක ඇත්තටම වෙනස් දේවල් දෙකක් කරයි. පළමු අනුවාදය ඔබට අවශ්‍ය පරිදි සාමාජිකයන් ඇද ගනු ඇත. දෙවන අනුවාදය ඔබ එය සමඟ කිසිවක් කිරීමට පෙර සියලු ප්‍රති results ල මතකයට පටවනු ඇත.

මේ සඳහා නිවැරදි හෝ වැරදි පිළිතුරක් නොමැත. වඩාත් සුදුසු වන්නේ තත්වය මත රඳා පවතී. උදාහරණයක් ලෙස, ඔබේ විමසුම සම්පුර්ණ කළ යුතු කාල සීමාවක් තිබේ නම් සහ ප්‍රති results ල සමඟ අර්ධ සංකීර්ණ යමක් කිරීමට ඔබට අවශ්‍ය නම්, දෙවන අනුවාදය වඩාත් සුදුසු විය හැකිය. නමුත් විශාල ප්‍රති results ල වලින් පරිස්සම් වන්න, විශේෂයෙන් ඔබ මෙම කේතය 32-බිට් ප්‍රකාරයේදී ධාවනය කරන්නේ නම්. මෙම ක්‍රමය සිදු කරන විට මට කිහිප වතාවක් OutOfMemory ව්‍යතිරේකයන් විසින් දෂ්ට කර ඇත.

මතක තබා ගත යුතු ප්‍රධාන දෙය මෙයයි: වෙනස්කම් කාර්යක්ෂමතාවයේ පවතී. මේ අනුව, ඔබ බොහෝ විට ඔබේ කේතය සරල කරන ඕනෑම දෙයක් සමඟ ගොස් එය වෙනස් කළ යුත්තේ පැතිකඩෙන් පසුව පමණි.


11

අස්වැන්න සඳහා විශාල භාවිතයන් දෙකක් ඇත

තාවකාලික එකතු කිරීම් නිර්මාණය කිරීම සමඟ අභිරුචි පුනරාවර්තනය සැපයීමට එය උපකාරී වේ. (සියලුම දත්ත පැටවීම සහ ලූප කිරීම)

එය රාජ්ය පුනරාවර්තනය කිරීමට උපකාරී වේ. (ප්‍රවාහය)

පහත දැක්වෙන්නේ ඉහත කරුණු දෙකට සහය දැක්වීම සඳහා මම සම්පූර්ණ නිරූපණයකින් නිර්මාණය කළ සරල වීඩියෝවකි

http://www.youtube.com/watch?v=4fju3xcm21M


11

මේ මොකක්ද ක්රිස් අලෙවි එම ප්රකාශ ගැන කියනවා භාෂා වැඩසටහන් මෙහිදී C # ,

අස්වැන්න ප්‍රතිලාභ ආපසු ලැබීමට සමාන නොවන බව මට සමහර විට අමතක වේ, අස්වැන්නෙන් පසු කේතය ක්‍රියාත්මක කළ හැකිය. උදාහරණයක් ලෙස, මෙහි පළමු නැවත පැමිණීමෙන් පසු කේතය කිසි විටෙකත් ක්‍රියාත්මක කළ නොහැක:

    int F() {
return 1;
return 2; // Can never be executed
}

ඊට වෙනස්ව, මෙහි පළමු අස්වැන්නෙන් පසු කේතය ක්‍රියාත්මක කළ හැකිය:

IEnumerable<int> F() {
yield return 1;
yield return 2; // Can be executed
}

මෙය බොහෝ විට if ප්‍රකාශයකින් මට දෂ්ට කරයි:

IEnumerable<int> F() {
if(...) { yield return 1; } // I mean this to be the only
// thing returned
yield return 2; // Oops!
}

මෙම අවස්ථා වලදී, නැවත පැමිණීම වැනි අස්වැන්න ප්‍රතිලාභ “අවසාන” නොවන බව මතක තබා ගැනීම ප්‍රයෝජනවත් වේ.


අපැහැදිලි බව අඩු කිරීමට කරුණාකර ඔබට හැකි විට, එය කළ හැකිද, කළ හැකිද? පළමුවැන්නාට නැවත පැමිණ දෙවන අස්වැන්න ක්‍රියාත්මක නොකිරීමට හැකිද?
ජොන්නෝ ක්‍රෝෆර්ඩ්

@ ජොහ්නෝ ක්‍රෝෆර්ඩ් දෙවන අස්වැන්න ප්‍රකාශය ක්‍රියාත්මක කරන්නේ IEnumerable හි දෙවන / ඊළඟ අගය ගණනය කළහොත් පමණි. එය සම්පූර්ණයෙන්ම සිදුවිය නොහැක්කකි, උදා F().Any()- මෙය පළමු ප්‍රති result ලය පමණක් ගණනය කිරීමට උත්සාහ කිරීමෙන් පසුව නැවත පැමිණේ. පොදුවේ ගත් කල, ඔබ IEnumerable yieldවැඩසටහන් තත්වයක් වෙනස් කිරීම මත විශ්වාසය නොතැබිය යුතුය , මන්ද එය සැබවින්ම අවුලුවනු නොලැබේ
සැක් ෆරාගර්

8

ඔබේ නිෂ්පාදන ගණනය කිරීම / නැවත ගණනය කිරීම සඳහා LINQ පන්තිය සමාන අස්වැන්නක් භාවිතා කරයි යැයි උපකල්පනය කිරීම, පළමු අනුවාදය වඩාත් කාර්යක්ෂම වන්නේ එය නැවත නැවත ක්‍රියාත්මක වන සෑම අවස්ථාවකම එක් අගයක් ලබා දෙන බැවිනි.

දෙවන උදාහරණය වන්නේ ගණන් ගැනීමේ යන්ත්‍රය / අනුකාරකය ToList () ක්‍රමය සමඟ ලැයිස්තුවකට පරිවර්තනය කිරීමයි. මෙයින් අදහස් කරන්නේ එය ගණන් කිරීමේ යන්ත්‍රයේ ඇති සියලුම අයිතමයන් අතින් අතින් නැවත සැකසෙන අතර පසුව පැතලි ලැයිස්තුවක් ලබා දෙයි.


8

මෙය කාරණයට අමතරව කාරුණික ය, නමුත් ප්‍රශ්නය හොඳම භාවිතයන් ලෙස ටැග් කර ඇති බැවින් මම ඉදිරියට ගොස් මගේ ශත දෙක විසි කරන්නෙමි. මෙම වර්ගයේ දේ සඳහා මම එය දේපලක් බවට පත් කිරීමට බෙහෙවින් කැමැත්තෙමි:

public static IEnumerable<Product> AllProducts
{
    get {
        using (AdventureWorksEntities db = new AdventureWorksEntities()) {
            var products = from product in db.Product
                           select product;

            return products;
        }
    }
}

ෂුවර්, එය තව ටිකක් බොයිලේරු තහඩුවකි, නමුත් මෙය භාවිතා කරන කේතය වඩා පිරිසිදු වනු ඇත:

prices = Whatever.AllProducts.Select (product => product.price);

එදිරිව

prices = Whatever.GetAllProducts().Select (product => product.price);

සටහන: ඔවුන්ගේ වැඩ කටයුතු කිරීමට යම් කාලයක් ගතවන කිසිදු ක්‍රමයක් සඳහා මම මෙය නොකරමි.


6

මේ ගැන කුමක් කිව හැකිද?

public static IEnumerable<Product> GetAllProducts()
{
    using (AdventureWorksEntities db = new AdventureWorksEntities())
    {
        var products = from product in db.Product
                       select product;

        return products.ToList();
    }
}

මම හිතන්නේ මේක ගොඩක් පිරිසිදුයි. පරීක්ෂා කිරීමට මා සතුව VS2008 නොමැත. කෙසේ වෙතත්, නිෂ්පාදන IEnumerable ක්‍රියාත්මක කරන්නේ නම් (පෙනෙන ආකාරයට - එය පුරෝකථන ප්‍රකාශයක භාවිතා වේ), මම එය කෙලින්ම ආපසු දෙන්නෙමි.


2
පිළිතුරු පළ කිරීම වෙනුවට වැඩි විස්තර ඇතුළත් කිරීමට කරුණාකර OP සංස්කරණය කරන්න.
බ්‍රයන් රස්මුසන්

හොඳයි, OP මට හරියටම අදහස් කරන්නේ කුමක්දැයි මට කියන්නට ඇත :-) ස්තූතියි
petr k.

ඔරිජිනල් පෝස්ට්, මම හිතන්නේ. මට සටහන් සංස්කරණය කළ නොහැක, එබැවින් මෙය යා යුතු මාර්ගය බව පෙනේ.
පෙටර් කේ.

5

මෙම අවස්ථාවේදී මම කේතයේ 2 වන අනුවාදය භාවිතා කිරීමට ඉඩ තිබුණි. ඔබ සතුව නිෂ්පාදනවල සම්පූර්ණ ලැයිස්තුවක් ඇති බැවින් සහ මෙම ක්‍රමවේදයෙහි “පාරිභෝගිකයා” අපේක්ෂා කරන්නේ එයයි, සම්පූර්ණ තොරතුරු නැවත අමතන්නා වෙත යැවීම අවශ්‍ය වේ.

මෙම ක්‍රමයට අමතන්නාට වරකට “එක්” තොරතුරු අවශ්‍ය නම් සහ ඊළඟ තොරතුරු පරිභෝජනය ඉල්ලුම මත පදනම් වේ නම්, අස්වැන්න ප්‍රතිලාභ භාවිතා කිරීම ප්‍රයෝජනවත් වන අතර එමඟින් ක්‍රියාත්මක කිරීමේ විධානය ඇමතුම්කරු වෙත ආපසු ලබා දෙන බවට සහතික වේ. තොරතුරු ඒකකයක් තිබේ.

කෙනෙකුට අස්වැන්න ප්‍රතිලාභ භාවිතා කළ හැකි උදාහරණ කිහිපයක් නම්:

  1. වරකට පියවරක දත්ත සඳහා ඇමතුම්කරු බලා සිටින සංකීර්ණ, පියවරෙන් පියවර ගණනය කිරීම
  2. GUI හි පේජිං - පරිශීලකයා කිසි විටෙකත් අවසාන පිටුවට ළඟා නොවිය හැකි අතර වත්මන් පිටුවේ අනාවරණය කිරීමට අවශ්‍ය වන්නේ උප තොරතුරු සමූහයක් පමණි

ඔබේ ප්‍රශ්නවලට පිළිතුරු සැපයීම සඳහා මම 2 අනුවාදය භාවිතා කරමි.


3

ලැයිස්තුව කෙලින්ම ආපසු එවන්න. ප්‍රතිලාභ:

  • එය වඩාත් පැහැදිලිය
  • ලැයිස්තුව නැවත භාවිතා කළ හැකිය. (iterator නොවේ) ඇත්ත වශයෙන්ම සත්‍ය නොවේ, ස්තූතියි ජෝන්

ලැයිස්තුවේ අවසානය දක්වා හෝ එහි අවසානයක් නොමැති විටදී ඔබට නැවත නැවත යෙදීමට සිදු නොවනු ඇතැයි ඔබ සිතන විට සිට ඔබ එය (අස්වැන්න) භාවිතා කළ යුතුය. නිදසුනක් ලෙස, සේවාදායකයා කැඳවීම යනු යම් පුරෝකථනයක් තෘප්තිමත් කරන පළමු නිෂ්පාදනය සෙවීමයි, එය උපක්‍රමශීලී භාවිතා කිරීම ගැන සලකා බැලිය හැකිය, එය ව්‍යාකූල උදාහරණයකි, නමුත් එය ඉටු කිරීමට වඩා හොඳ ක්‍රම තිබේ. මූලික වශයෙන්, මුළු ලැයිස්තුවම ගණනය කළ යුතු බව ඔබ කල්තියා දන්නේ නම්, එය ඉදිරියෙන් කරන්න. එය එසේ නොවේ යැයි ඔබ සිතන්නේ නම්, iterator අනුවාදය භාවිතා කිරීම ගැන සලකා බලන්න.


එය IEnumerable <T> වලින් නැවත පැමිණෙන බව අමතක නොකරන්න, IEnumerator <T> නොවේ - ඔබට නැවත GetEnumerator අමතන්න.
ජෝන් ස්කීට්

ඔබ කල්තියා දැන සිටියත් මුළු ලැයිස්තුවම ගණනය කිරීමට අවශ්‍ය වනු ඇත අස්වැන්න ප්‍රතිලාභ භාවිතා කිරීම තවමත් ප්‍රයෝජනවත් විය හැකිය. එක් උදාහරණයක් නම් එකතුවෙහි අයිතම සිය දහස් ගණනක් අඩංගු වන විට ය.
Val

1

නිශ්චිත එකතුවක් සඳහා රාජ්‍ය යන්ත්‍රය නඩත්තු කිරීම සඳහා අස්වැන්න ප්‍රතිලාභ යතුරු පුවරුව භාවිතා කරයි. අස්වැන්න ආපසු ලබා දෙන යතුරුපුවරුව සීඑල්ආර් දකින ඕනෑම තැනක, සීඑල්ආර් එම කේත කැබැල්ලට ගණන් ගැනීමේ රටාවක් ක්‍රියාත්මක කරයි. මෙම වර්ගයේ ක්‍රියාත්මක කිරීම සංවර්ධකයාට සියලු වර්ගවල ජලනල කාර්මික ශිල්පීන්ට උදව් කරයි.

සංවර්ධකයා කිසියම් එකතුවක් පෙරහන් කරන්නේ නම්, එකතු කිරීම නැවත සිදු කර එම නව වස්තු එකතු කර ගනී යැයි සිතමු. මේ ආකාරයේ ජලනල තරමක් ඒකාකාරී ය.

මෙම ලිපියෙන් මෙහි මූලික පදය ගැන වැඩි විස්තර .


-4

අස්වැන්න භාවිතය උත්පාදක යන්ත්‍රයක් ආපසු ලබා දෙන බව හැර, යතුරුපදයේ ප්‍රතිලාභයට සමාන වේ . හා උත්පාදක වස්තුවක් තරණය ඇත වරක් .

අස්වැන්නෙන් වාසි දෙකක් ඇත:

  1. ඔබට මෙම අගයන් දෙවරක් කියවීමට අවශ්‍ය නැත;
  2. ඔබට බොහෝ ළමා නෝඩ් ලබා ගත හැකි නමුත් ඒවා සියල්ලම මතකයේ තබා ගත යුතු නැත.

තවත් පැහැදිලි පැහැදිලි කිරීමක් ඔබට උදව් විය හැකිය.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.