ফোরচ লুপের অভ্যন্তরে বা বাইরে কোনও ভেরিয়েবল ঘোষণা করা: কোনটি দ্রুত / ভাল?


94

এর মধ্যে কোনটি দ্রুত / সর্বোত্তম?

এইটা:

List<User> list = new List<User>();
User u;

foreach (string s in l)
{
    u = new User();
    u.Name = s;
    list.Add(u);
}

বা এটি একটি:

List<User> list = new List<User>();

foreach (string s in l)
{
    User u = new User();
    u.Name = s;
    list.Add(u);
}

আমার নবাগত-বিকাশকারী দক্ষতা আমাকে প্রথমটি আরও ভাল বলে দেয়, তবে আমার এক বন্ধু আমাকে ভুল বলে, তবে দ্বিতীয়টি আরও ভাল হওয়ার কারণ সম্পর্কে আমাকে কোনও কারণ দিতে পারেনি।

অভিনয়ে কি আদৌ কোনও পার্থক্য আছে?

উত্তর:


115

পারফরম্যান্স-ভিত্তিক উভয় উদাহরণ একই আইএলে সংকলিত, সুতরাং কোনও পার্থক্য নেই।

দ্বিতীয়টি আরও ভাল, কারণ এটি uকেবলমাত্র লুপের অভ্যন্তরে ব্যবহৃত হলে এটি আরও স্পষ্টভাবে আপনার অভিপ্রায় প্রকাশ করে।


10
উল্লেখ্য যে হয় একটি পার্থক্য যদি পরিবর্তনশীল একটি ল্যামডা অভিব্যক্তি বা বেনামী প্রতিনিধি ক্যাপচার করা হয়; দেখতে বাইরের চলক ফাঁদ
dtb

উভয়কে কেন একই আইএল সংকলিত হয় তা আপনি ব্যাখ্যা করতে পারেন? আমি বেশ নিশ্চিত যে সি # জাভাস্ক্রিপ্টের মতো ফাংশনের শীর্ষ পর্যন্ত ভেরিয়েবলের ঘোষণাগুলি উত্তোলন করে না।
স্টাইলফ্ল

4
@ স্টাইফ্লে আপনার প্রশ্নের উত্তর এখানে ।
ডেভিড শেরেট

স্ট্যাক ওভারফ্লো লিঙ্কগুলি নিম্নলিখিত বিশদ উত্তর সরবরাহ করে: 1) জন হান্না এবং 2) স্ট্রিপলিং
ওয়ারিয়র

14

যাই হোক না কেন, সবচেয়ে ভাল উপায় হ'ল একটি নাম ব্যবহারকারী কনস্ট্রাক্টর ব্যবহার করা ... বা অন্যথায়, কোঁকড়ানো-ব্রেস সূচকটি শোষণ করুন:

foreach (string s in l)
{
    list.Add(new User(s));
}

বা

foreach (string s in l)
{
    list.Add(new User() { Name = s });
}

বা আরও ভাল লিনকিউ:

var list = l.Select( s => new User { Name = s});

এখন, যদিও আপনার প্রথম উদাহরণটি, কিছু ক্ষেত্রে, অকারণে দ্রুততর হতে পারে, দ্বিতীয়টি আরও ভাল কারণ এটি আরও বেশি পাঠযোগ্য এবং সংকলকটি পরিবর্তনশীলটিকে (এবং এটি পুরোপুরি বাদ দিতে পারে) বাদ দিতে পারে কারণ এটি এর ক্ষেত্রের বাইরে নয় foreach


6
দিনের নেক্রোফিলিক মন্তব্য: "বা আরও ভাল লিনকিউ"। অবশ্যই এটি কোডের এক লাইন, এবং এটি আমাদের বিকাশকারীদের ভাল মনে করে। তবে চার লাইনের সংস্করণটি আরও বেশি বোধগম্য এবং এর মাধ্যমে বজায় রাখা যায়।
ওসকার অসটগার্ড

4
খুব কমই। লিনকিউ সংস্করণে আমি জানি যে আমি যা করছি তা স্থাবর এবং এটি প্রতিটি উপাদানকে নিয়ে কাজ করে।
টর্ডেক

6

একটি ঘোষণার ফলে কোনও কোড কার্যকর করা হয় না, সুতরাং এটি কোনও পারফরম্যান্স সমস্যা নয়।

দ্বিতীয়টি যা বোঝায় তা হ'ল এবং যদি আপনি এটি দ্বিতীয় উপায়ে করেন তবে আপনার বোকা ত্রুটি হওয়ার সম্ভাবনা কম। সর্বদা প্রয়োজনীয় ক্ষুদ্রতম স্কোপগুলিতে ভেরিয়েবলগুলি ঘোষণার চেষ্টা করুন।

এবং তদতিরিক্ত, লিনক ব্যবহারের আরও ভাল উপায়:

List<User> users = l.Select(name => new User{ Name = name }).ToList();

4
আমি "সর্বদা প্রয়োজনীয় ক্ষুদ্রতম স্কোপগুলিতে ভেরিয়েবলগুলি ঘোষণার চেষ্টা করি" এই লাইনটি আমি পছন্দ করি। আমি মনে করি একটি লাইন খুব ভাল প্রশ্নের উত্তর দিতে পারে।
মনজুর

5

আপনি যখনই পারফরম্যান্স সম্পর্কে কোনও প্রশ্ন করবেন তখন কেবলমাত্র পরিমাপ করা - আপনার পরীক্ষার চারপাশে একটি লুপ চালানো এবং এটির সময়।

আপনার প্রশ্নের উত্তর দেওয়ার জন্য :-) পরিমাপ না করে বা উত্পন্ন ilasm না দেখে - কোনও তাত্পর্য অর্থবহ সংখ্যায় পুনরাবৃত্তিযোগ্য হিসাবে চিহ্নিত হবে না এবং আপনার কোডের সবচেয়ে ব্যয়বহুল ক্রিয়াকলাপ কয়েকটি আদেশ দ্বারা ব্যবহারকারী বরাদ্দ হওয়ার সম্ভাবনা রয়েছে প্রস্থের, তাই কোডের স্বচ্ছতার দিকে মনোনিবেশ করুন (আপনার যেমনটি সাধারণভাবে হওয়া উচিত) এবং 2 দিয়ে যান।

ওহ, এর দেরি হয়ে গেছে এবং আমি অনুমান করি যে আমি কেবল বলার চেষ্টা করছি যে এই ধরণের জিনিস সম্পর্কে চিন্তা করবেন না বা এই জাতীয় বিশদ সম্পর্কে ধরা পড়বেন না caught

কে


টিপসটির জন্য টিএক্স, আমি মনে করি যে আমি অন্য কোনও জিনিস নিয়ে সময় কাটিয়ে যাচ্ছি যেহেতু সে সম্পর্কে
মার্কাস

আপনি যদি পারফরম্যান্সকে কীভাবে প্রভাবিত করে তা খতিয়ে দেখার সাথে যদি আরও যেতে চান তবে একটি কোড প্রোফাইলার ব্যবহার করে দেখুন। যদি অন্য কিছু না হয় তবে এটি আপনাকে কী ধরণের কোড এবং ক্রিয়াকলাপ সবচেয়ে বেশি সময় নেয় সে সম্পর্কে একটি ধারণা দিতে শুরু করবে। প্রোফাইলশার্প এবং একাটেক প্রোফিলারগুলি নিখরচায় এবং আপনাকে শুরু করার জন্য যথেষ্ট।
কেভিন শেয়া

1

দ্বিতীয়টি আরও ভাল। আপনার প্রতিটি পুনরাবৃত্তিতে একটি নতুন ব্যবহারকারী থাকার অর্থ।


1

প্রযুক্তিগতভাবে, প্রথম উদাহরণটি কয়েকটি ন্যানোসেকেন্ডগুলি সংরক্ষণ করবে কারণ স্ট্যাক ফ্রেমটি কোনও নতুন ভেরিয়েবল বরাদ্দ করার জন্য সরানো হবে না, তবে এটি সিপিইউর পরিমাণের মতো এমন একটি ছোট পরিমাণ যা আপনি এটি লক্ষ্য করবেন না, যদি সংকলকটি এটি না করে তবে যেকোনও পার্থক্য অপ্টিমাইজ করুন।


আমি নিশ্চিত যে সিএলআর প্রতিটি লুপের পুনরাবৃত্তিতে "নতুন পরিবর্তনশীল" বরাদ্দ করে না pretty
dtb

ঠিক আছে, সংকলকটি এটিকে আরও ভালভাবে অনুকূল করতে পারে তবে কোনও লুপের কোনও ভেরিয়েবলের জন্য স্ট্যাক স্পেস বরাদ্দ করতে হবে। এটি বাস্তবায়ন নির্ভর করবে এবং একটি বাস্তবায়ন কেবল স্ট্যাক ফ্রেমটিকে একই রকম রাখতে পারে, অন্যদিকে (মনো বলুন) স্ট্যাকটি মুক্তি দিতে পারে এবং প্রতিটি লুপে পুনরায় তৈরি করতে পারে।
এরিক ফানকেনবাশ

16
কোনও পদ্ধতিতে সমস্ত স্থানীয় ভেরিয়েবল (শীর্ষ স্তরের বা লুপে নেস্ট করা) আইএল-এর পদ্ধতি-স্তরের ভেরিয়েবলগুলিতে সংকলিত হয়। পদ্ধতিটি কার্যকর হওয়ার আগে ভেরিয়েবলের জন্য স্থান বরাদ্দ করা হয়, যখন সি # তে ঘোষণার সাথে একটি শাখা পৌঁছে যায় না।
dtb

4
@dtb আপনার কি এই দাবির কোনও উত্স আছে?
স্টাইলফেল

1

এই পরিস্থিতিতে, দ্বিতীয় সংস্করণটি আরও ভাল।

সাধারণভাবে, যদি আপনাকে কেবল পুনরাবৃত্তির মূল অংশের মধ্যে মানটি অ্যাক্সেস করতে হয় তবে দ্বিতীয় সংস্করণটি চয়ন করুন। অন্যদিকে, যদি কিছু চূড়ান্ত অবস্থা থাকে তবে ভেরিয়েবল লুপের মূল অংশ ছাড়িয়ে যাবে, তারপরে ঘোষণা করুন তারপরে প্রথম সংস্করণটি ব্যবহার করুন।




0

আমি এই সমস্যাটি যাচাই করতে গিয়েছিলাম।

namespace Test
{
  class Foreach
  {
    string[] names = new[] { "ABC", "MNL", "XYZ" };

    void Method1()
    {
      List<User> list = new List<User>();
      User u;

      foreach (string s in names)
      {
        u = new User();
        u.Name = s;
        list.Add(u);
      }
    }

    void Method2()
    {

      List<User> list = new List<User>();

      foreach (string s in names)
      {
        User u = new User();
        u.Name = s;
        list.Add(u);
      }
    }
  }

  public class User { public string Name; }
}

সিআইএল ছড়িয়ে পড়ে যে কেবলমাত্র ভেরিয়েবলগুলি একটি পৃথক নম্বর পেতে পারে।

এখানে চিত্র বর্ণনা লিখুন

তাই আমি এমন কিছু প্রস্তুত করেছিলাম যা আরও ভাল হওয়ার কথা ছিল।

namespace Test
{
  class Loop
  { 

    public TimeSpan method1 = new TimeSpan();
    public TimeSpan method2 = new TimeSpan();

    Stopwatch sw = new Stopwatch();

    public void Method1()
    {
      sw.Restart();

      C c;
      C c1;
      C c2;
      C c3;
      C c4;

      int i = 1000;
      while (i-- > 0)
      {
        c = new C();
        c1 = new C();
        c2 = new C();
        c3 = new C();
        c4 = new C();        
      }

      sw.Stop();
      method1 = method1.Add(sw.Elapsed);
    }

    public void Method2()
    {
      sw.Restart();

      int i = 1000;
      while (i-- > 0)
      {
        var c = new C();
        var c1 = new C();
        var c2 = new C();
        var c3 = new C();
        var c4 = new C();
      }

      sw.Stop();
      method2 = method2.Add(sw.Elapsed);
    }
  }

  class C { }
}

সিআইএল কোনও পার্থক্য দেখায় না।

এখানে চিত্র বর্ণনা লিখুন

যেমন ইতিমধ্যে ইঙ্গিত করা হয়েছিল যে ঘোষণাপত্র বরাদ্দ নয় তাই এতে কোনও পারফরম্যান্স জরিমানা নেই।

পরীক্ষা

namespace Test
{
  class Foreach
  {
    string[] names = new[] { "ABC", "MNL", "XYZ" };

    public TimeSpan method1 = new TimeSpan();
    public TimeSpan method2 = new TimeSpan();

    Stopwatch sw = new Stopwatch();

    void Method1()
    {
      sw.Restart();

      List<User> list = new List<User>();
      User u;

      foreach (string s in names)
      {
        u = new User();
        u.Name = s;
        list.Add(u);
      }

      sw.Stop();
      method1 = method1.Add(sw.Elapsed);
    }

    void Method2()
    {
      sw.Restart();

      List<User> list = new List<User>();

      foreach (string s in names)
      {
        User u = new User();
        u.Name = s;
        list.Add(u);
      }

      sw.Stop();
      method2 = method2.Add(sw.Elapsed);
    }
  }

  public class User { public string Name; }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.