অনুমিত "স্টেট মেশিন" সনাক্ত করা


17

আমি মাত্র একটি # আকর্ষণীয় নিবন্ধ পড়লাম সি # ফলনের সাথে খুব সুন্দর হয়ে উঠছি cute

এটি আমাকে অবাক করে দিয়েছিল যে কোনও আইএননামারেবল একটি প্রকৃত গণনাকারী সংগ্রহ, বা যদি এটি কোনও উত্পাদ কীওয়ার্ড সহ কোনও রাষ্ট্রীয় মেশিন তৈরি করা হয় তবে এটি নির্ধারণের সেরা উপায়টি।

উদাহরণস্বরূপ, আপনি DoubleXValue (নিবন্ধ থেকে) এমন কিছুতে পরিবর্তন করতে পারেন:

private void DoubleXValue(IEnumerable<Point> points)
{
    if(points is List<Point>)
      foreach (var point in points)
        point.X *= 2;
    else throw YouCantDoThatException();
}

প্রশ্ন 1) এটি করার আরও ভাল উপায় আছে?

প্রশ্ন 2) একটি এপিআই তৈরি করার সময় আমার কি এই বিষয়টি নিয়ে চিন্তা করা উচিত?


1
আপনার কোনও কংক্রিটের পরিবর্তে একটি ইন্টারফেস ব্যবহার করা উচিত এবং নীচে নীচে নিক্ষেপ করা উচিত, ICollection<T>সমস্ত সংগ্রহ যেমন নয় তেমন একটি ভাল পছন্দ হবে List<T>। উদাহরণস্বরূপ, অ্যারে Point[]প্রয়োগ করে IList<T>তবে তা হয় না List<T>
ট্রেভর পিলি 21'13

3
পরিবর্তনীয় প্রকারের সমস্যাটিতে স্বাগতম। অগণনীয় স্পষ্টতই একটি অপরিবর্তনীয় ডেটা ধরণের বলে মনে করা হয়, তাই পরিবর্তনের বাস্তবায়নগুলি এলএসপি লঙ্ঘন। এই নিবন্ধটি পার্শ্ব প্রতিক্রিয়াগুলির ঝুঁকির একটি নিখুঁত ব্যাখ্যা, সুতরাং আপনার সি # প্রকারগুলি যথাসম্ভব পার্শ্ব প্রতিক্রিয়ামুক্ত রাখতে লেখার অনুশীলন করুন এবং আপনার এ সম্পর্কে কখনও উদ্বিগ্ন হওয়ার দরকার নেই।
জিমি হোফা

1
@ জিমিহোফা IEnumerableএই অর্থে অপরিবর্তনীয় যে আপনি একটি সংকলন গণনা করার সময় (সংযোজন / অপসারণ) সংশোধন করতে পারবেন না, তবে তালিকার অবজেক্টগুলি যদি পরিবর্তনীয় হয় তবে তালিকাটি গণনার সময় সেগুলি সংশোধন করা পুরোপুরি যুক্তিসঙ্গত।
ট্রেভর পিলি

পছন্দ করুন যদি সংগ্রহটি অপরিবর্তনীয় বলে আশা করা হয়, তবে গ্রাহকের কাছ থেকে প্রত্যাশাটি হ'ল সদস্যরা বাইরের অভিনেতাদের দ্বারা পরিবর্তিত হবে না, এটিকে পার্শ্ব প্রতিক্রিয়া বলা হবে এবং অনিচ্ছাকৃত প্রত্যাশা লঙ্ঘন করবে। পোলা লঙ্ঘন করে এবং কার্যকরভাবে এলএসপি করে।
জিমি হোফা

কিভাবে ব্যবহার সম্পর্কে ToList? msdn.microsoft.com/en-us/library/bb342261.aspx এটি উত্পাদনের দ্বারা উত্পাদিত হয়েছে কিনা তা সনাক্ত করে না, পরিবর্তে এটি এটিকে অপ্রাসঙ্গিক করে তোলে।
লুস্কুবাল

উত্তর:


22

আপনার প্রশ্নটি আমি যেমন বুঝতে পেরেছি বলে মনে হচ্ছে এটি ভুল ভিত্তির উপর ভিত্তি করে। আমি যুক্তিটি পুনর্গঠন করতে পারি কিনা তা আমাকে দেখতে দিন:

  • সংযুক্ত-নিবন্ধটি বর্ণনা করে যে কীভাবে স্বয়ংক্রিয়ভাবে উত্পন্ন সিকোয়েন্সগুলি একটি "অলস" আচরণ প্রদর্শন করে এবং দেখায় যে এটি কীভাবে একটি পাল্টা-স্বজ্ঞাত ফলাফলের দিকে নিয়ে যেতে পারে।
  • অতএব আমি সনাক্ত করতে পারি যে আইনিউমারেবলের প্রদত্ত একটি উদাহরণ স্বয়ংক্রিয়ভাবে উত্পন্ন হয়েছে কিনা তা যাচাই করে পরীক্ষা করে এই অলস আচরণটি প্রদর্শন করছে কিনা।
  • আমি কেমন করে ঐটি করি?

সমস্যাটি হ'ল দ্বিতীয় অনুমানটি মিথ্যা। এমনকি যদি আপনি সনাক্ত করতে পারেন যে প্রদত্ত আইএননামারেবল একটি পুনরুক্তিকারী ব্লক রূপান্তরের ফলাফল ছিল (এবং হ্যাঁ, এটি করার উপায় রয়েছে) এটি সহায়তা করবে না কারণ অনুমানটি ভুল। আসুন উদাহরণস্বরূপ।

class M { public int P { get; set; } }
class C
{
  public static IEnumerable<M> S1()
  {
    for (int i = 0; i < 3; ++i) 
      yield return new M { P = i };
  }

  private static M[] ems = new M[] 
  { new M { P = 0 }, new M { P = 1 }, new M { P = 2 } };
  public static IEnumerable<M> S2()
  {
    for (int i = 0; i < 3; ++i)
      yield return ems[i];
  }

  public static IEnumerable<M> S3()
  {
    return new M[] 
    { new M { P = 0 }, new M { P = 1 }, new M { P = 2 } };
  }

  private class X : IEnumerable<M>
  {
    public IEnumerator<X> GetEnumerator()
    {
      return new XEnum();
    }
    // Omitted: non generic version
    private class XEnum : IEnumerator<X>
    {
      int i = 0;
      M current;
      public bool MoveNext()
      {
        current = new M() { P = i; }
        i += 1;
        return true;
      }
      public M Current { get { return current; } }
      // Omitted: other stuff.
    }
  }

  public static IEnumerable<M> S4()
  {
    return new X();
  }

  public static void Add100(IEnumerable<M> items)
  {
    foreach(M item in items) item.P += 100;
  }
}

ঠিক আছে, আমাদের চারটি পদ্ধতি রয়েছে। এস 1 এবং এস 2 স্বয়ংক্রিয়ভাবে সিকোয়েন্সগুলি উত্পন্ন হয়; এস 3 এবং এস 4 ম্যানুয়ালি উত্পাদিত ক্রম হয়। এখন ধরুন আমাদের কাছে রয়েছে:

var items = C.Sn(); // S1, S2, S3, S4
S.Add100(items);
Console.WriteLine(items.First().P);

এস 1 এবং এস 4 এর ফলাফল 0 হবে; প্রতিবার আপনি ক্রমটি অঙ্ক করবেন, আপনি এম তৈরির একটি নতুন রেফারেন্স পাবেন। এস 2 এবং এস 3 এর ফলাফল 100 হবে; প্রতিবার আপনি ক্রমটি গণনা করার সময়, আপনি শেষ বারের মতো এম এর একই রেফারেন্স পাবেন। সিকোয়েন্স কোডটি স্বয়ংক্রিয়ভাবে উত্পন্ন হয়েছে কিনা তা প্রশ্নে অর্থেগোনাল কিনা তা গণনা করা অবজেক্টগুলির রেফারেনশিয়াল পরিচয় আছে কি না। এই দুটি বৈশিষ্ট্য - স্বয়ংক্রিয় প্রজন্ম এবং রেফারেনশিয়াল পরিচয় - একে অপরের সাথে আসলে কিছুই করার নেই। আপনি যে নিবন্ধটির সাথে লিঙ্ক করেছেন সেগুলি তাদের কিছুটা মিশিয়ে দেয়।

যদি না একটি ক্রম প্রদানকারী সবসময় বস্তু আপ করে চাইবে যেমন নথিভুক্ত করা উল্লেখ পরিচয় , এটা যে এটা এত করে অনুমান করা বিজ্ঞতার কাজ নয়।


2
আমরা সবাই জানি এখানে আপনার সঠিক উত্তর থাকবে, এটি একটি প্রদত্ত; তবে আপনি যদি "রেফারেনশিয়াল আইডেন্টিটি" শব্দটির আরও কিছুটা সংজ্ঞা দিতে পারেন তবে এটি ভাল হতে পারে, আমি এটিকে "অপরিবর্তনীয়" হিসাবে পড়ছি তবে এটি কারণ আমি সি # তে অপরিবর্তনীয় নতুন বস্তুর সাথে প্রতিটি প্রাপ্তি বা মান টাইপ প্রত্যাবর্তন করেছি, যা আমি মনে করি আপনি একই জিনিস উল্লেখ করছেন। যদিও মঞ্জুরিপ্রাপ্ত অপরিবর্তনীয়তা বিভিন্ন উপায়ে হতে পারে তবে এটি সি # এর একমাত্র যুক্তিযুক্ত উপায় (যা আমি অবগত, আপনি যে উপায়গুলি সম্পর্কে অবগত নন সে সম্পর্কে আপনি ভাল জানেন)।
জিমি হোফা

2
@ জিমিহোফা: অবজেক্ট.অরফারেন্সএকুয়ালস (x, y) সত্য হলে দুটি অবজেক্টের রেফারেন্স x এবং y এর "রেফারেনশিয়াল পরিচয়" থাকে।
এরিক লিপার্ট

উত্স থেকে সরাসরি প্রতিক্রিয়া পেতে সর্বদা দুর্দান্ত। ধন্যবাদ এরিক
কন্ডিশন

10

আমি মনে করি মূল ধারণাটি হ'ল আপনার যে কোনও IEnumerable<T>সংগ্রহকে অপরিবর্তনীয় হিসাবে বিবেচনা করা উচিত : আপনি এটি থেকে অবজেক্টগুলিকে সংশোধন করা উচিত নয়, আপনার নতুন বস্তু সহ একটি নতুন সংগ্রহ তৈরি করা উচিত:

private IEnumerable<Point> DoubleXValue(IEnumerable<Point> points)
{
    foreach (var point in points)
        yield return new Point(point.X * 2, point.Y);
}

(বা লিনকিউ ব্যবহার করে একই আরও সংক্ষেপে লিখুন Select()))

আপনি যদি সংগ্রহের আইটেমগুলি সংশোধন করতে চান তবে ব্যবহার করবেন না IEnumerable<T>, ব্যবহার করবেন না IList<T>(বা সম্ভবত IReadOnlyList<T>আপনি যদি সংগ্রহটি নিজেই পরিবর্তন করতে না চান তবে কেবল এটিতে আইটেমগুলি থাকে এবং আপনি নেট .৪.৪):

private void DoubleXValue(IList<Point> points)
{
    foreach (var point in points)
        point.X *= 2;
}

এইভাবে, যদি কেউ আপনার পদ্ধতিটি সাথে ব্যবহার করার চেষ্টা করে তবে IEnumerable<T>এটি সংকলনের সময় ব্যর্থ হবে।


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

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

@ জিমি হোফা: আমি একমত আমি আরও একধাপ এগিয়ে গিয়ে IEnumerableএকাধিকবার পুনরাবৃত্তি এড়াতে চেষ্টা করি । ToList()তালিকার উপরে কল করে এবং পুনরাবৃত্তি করার মাধ্যমে একাধিকবার করার দরকার পড়তে পারে , যদিও ওপির প্রদর্শিত নির্দিষ্ট ক্ষেত্রে আমি ডাবলএক্সভ্যালু থাকার ক্ষেত্রে সাইকিকের সমাধানটিও একটি আইনামেবল ফিরিয়ে দিতে পছন্দ করি। অবশ্যই, বাস্তব কোডে আমি সম্ভবত LINQএই ধরণের তৈরি করতে ব্যবহার করব IEnumerable। তবে, ওপিকের yieldপ্রশ্নের প্রসঙ্গে স্বিকের পছন্দটি বোধগম্য।
ব্রায়ান

@ ব্রায়ান হ্যাঁ, আমি আমার বক্তব্য তৈরি করতে কোডটি খুব বেশি পরিবর্তন করতে চাইনি। বাস্তব কোডে, আমি ব্যবহার করতে হবে Select()। এবং এর একাধিক পুনরাবৃত্তির বিষয়ে IEnumerable: রিসার্পার এটির জন্য সহায়ক, কারণ আপনি যখন এটি করবেন তখন এটি আপনাকে সতর্ক করতে পারে।
সুইভ

5

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

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

ডাউনভোটারদের জন্য সম্পাদনা করুন দয়া করে ফিরে যান এবং মনোযোগ দিয়ে প্রশ্নটি পড়ুন। ওপি IEnumerableতার এপিআই পদ্ধতিতে যাওয়ার আগে উদাহরণগুলি বাস্তবায়িত হয়েছে কিনা তা নিশ্চিত করার জন্য একটি উপায় জিজ্ঞাসা করছে । আমার উত্তর সেই প্রশ্নের ঠিকানা দেয়। যথাযথভাবে ব্যবহারের উপায় সম্পর্কিত একটি বিস্তৃত সমস্যা রয়েছে IEnumerableএবং অবশ্যই ওপি কর্তৃক প্রেরিত কোডটির প্রত্যাশাগুলি সেই বিস্তৃত সমস্যার একটি ভুল বোঝাবুঝির ভিত্তিতে তৈরি হয়েছে, তবে ওপি কীভাবে সঠিকভাবে ব্যবহার করবেন IEnumerable, বা কীভাবে অপরিবর্তনীয় প্রকারের সাথে কাজ করবেন তা জিজ্ঞাসাবাদ করেনি । কোনও প্রশ্নের উত্তর না দেওয়ার জন্য আমাকে উত্সাহ দেওয়া ঠিক নয় যা উত্থাপিত হয়নি।

* আমি এই শব্দটি ব্যবহার করি reify, অন্যরা stabilizeবা ব্যবহার করে materialize। আমি মনে করি না এখনও জনগোষ্ঠী একটি সাধারণ সম্মেলন গ্রহণ করেছে।


2
ICollectionএবং এর সাথে একটি সমস্যা IListহ'ল তারা পরিবর্তনযোগ্য (বা কমপক্ষে সেভাবে দেখুন)। IReadOnlyCollectionএবং IReadOnlyList.NET 4.5 থেকে এই সমস্যার কয়েকটি সমাধান করুন।
সুইভ

ডাউনভোটটি ব্যাখ্যা করুন?
ম্যাটড্যাভি

1
আমি একমত নই যে আপনি যে ধরণের ব্যবহার করছেন তা আপনার পরিবর্তন করা উচিত। অণনযোগ্য একটি দুর্দান্ত ধরণের এবং এটি প্রায়শই অপরিবর্তনীয়তার সুবিধা পেতে পারে। আমি মনে করি আসল সমস্যা হ'ল সি # তে অপরিবর্তনীয় ধরণের সাথে কীভাবে কাজ করা যায় তা মানুষ বুঝতে পারে না। অবাক করার মতো বিষয় নয়, এটি একটি অত্যন্ত রাষ্ট্রভাষার ভাষা, তাই এটি অনেকগুলি সি # দেব-দের কাছে একটি নতুন ধারণা।
জিমি হোফা

কেবল অগণনীয় স্থগিতাদেশ কার্যকর করতে অনুমতি দেয়, সুতরাং প্যারামিটার হিসাবে এটি অস্বীকার করা সি # এর পুরো বৈশিষ্ট্যটি সরিয়ে দেয়
জিমি হোফা

2
আমি এটিকে ভোট দিয়েছি কারণ আমার ধারণা এটি ভুল wrong আমি মনে করি এটি এসই এর চেতনায় রয়েছে, যাতে লোকেরা ভুল তথ্যে স্টক না দেয় তা নিশ্চিত করে আমাদের সকলের উপর নির্ভর করে সেই উত্তরগুলি ভোট দেওয়া উচিত। হতে পারে আমি ভুল, পুরোপুরি সম্ভব যে আমি ভুল এবং আপনি সঠিক। ভোটদানের মাধ্যমে সিদ্ধান্ত নেওয়া বৃহত্তর সম্প্রদায়ের to দুঃখিত আপনি এটি ব্যক্তিগতভাবে নিচ্ছেন, যদি এটির কোনও সান্ত্বনা থাকে তবে আমি লিখেছি এবং সংক্ষেপে মুছে ফেলা হয়েছে এমন অনেক নেতিবাচক জবাব পেয়েছি কারণ আমি সম্প্রদায়টি এটি ভুল বলে মনে করি তাই এটি আমার অসম্ভব সঠিক।
জিমি হোফা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.