سؤال

.Net 3.5 لا يدعم المجموعات.سيء جدًا، ولكن لست متأكدًا مما إذا كان الإصدار المستقبلي من .net سيدعم الصفوف أم لا؟

هل كانت مفيدة؟

المحلول

لقد قرأت للتو هذا المقال من مجلة MSDN: بناء توبل

وهنا مقتطفات:

يقدم الإصدار 4.0 القادم لـ Microsoft .NET Framework نوعًا جديدًا يسمى System.Tuple.System.Tuple عبارة عن مجموعة ثابتة من البيانات المكتوبة بشكل غير متجانس.

 

مثل صفيف ، يحتوي Tuple على حجم ثابت لا يمكن تغييره بمجرد إنشاءه.على عكس الصفيف ، قد يكون كل عنصر في Tuple نوعًا مختلفًا ، ويمكن للترجمة ضمان كتابة قوية لكل عنصر.

 

يوجد بالفعل مثال واحد على tuple تطفو حول Framework Microsoft .NET ، في مساحة الاسم.KeyValuePair.على الرغم من أنه يمكن اعتبار keyvaluepair مثل Tuple ، نظرًا لأنهما كلا النوعين اللذين يحتويان على شيئين ، فإن KeyValuepair يشعران مختلفًا عن Tuple لأنه يثير علاقة بين القيمتين اللتين تخزنهما (وسبب وجيه ، لأنه يدعم فئة القاموس ).

علاوة على ذلك ، يمكن أن يكون حجم tuples بحجم تعسفي ، في حين أن KeyValuepair يحمل شيئين فقط:مفتاح وقيمة.


في حين أن بعض اللغات مثل F# لها بناء جملة خاص للصفوف، يمكنك استخدام نوع الصف الشائع الجديد من أي لغة.بإعادة النظر في المثال الأول، يمكننا أن نرى أنه على الرغم من فائدة الصفوف، إلا أنها يمكن أن تكون مطولة بشكل مفرط في اللغات التي لا تحتوي على بناء جملة للصفوف:

class Program {
    static void Main(string[] args) {
        Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
        PrintStringAndInt(t.Item1, t.Item2);
    }
    static void PrintStringAndInt(string s, int i) {
        Console.WriteLine("{0} {1}", s, i);
    }
}

باستخدام الكلمة الأساسية var من الإصدار C# 3.0، يمكننا إزالة توقيع النوع الموجود على متغير المجموعة، مما يسمح بتعليمات برمجية أكثر قابلية للقراءة إلى حد ما.

var t = new Tuple<string, int>("Hello", 4);

لقد أضفنا أيضًا بعض أساليب المصنع إلى فئة Tuple الثابتة مما يجعل من السهل إنشاء صفوف في لغة تدعم استنتاج النوع، مثل C#.

var t = Tuple.Create("Hello", 4);

نصائح أخرى

#region tuples

    public class Tuple<T>
    {
        public Tuple(T first)
        {
            First = first;
        }

        public T First { get; set; }
    }

    public class Tuple<T, T2> : Tuple<T>
    {
        public Tuple(T first, T2 second)
            : base(first)
        {
            Second = second;
        }

        public T2 Second { get; set; }
    }

    public class Tuple<T, T2, T3> : Tuple<T, T2>
    {
        public Tuple(T first, T2 second, T3 third)
            : base(first, second)
        {
            Third = third;
        }

        public T3 Third { get; set; }
    }

    public class Tuple<T, T2, T3, T4> : Tuple<T, T2, T3>
    {
        public Tuple(T first, T2 second, T3 third, T4 fourth)
            : base(first, second, third)
        {
            Fourth = fourth;
        }

        public T4 Fourth { get; set; }
    }

    #endregion

ولجعل التصريحات أجمل:

public static class Tuple
{
    //Allows Tuple.New(1, "2") instead of new Tuple<int, string>(1, "2")
    public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2)
    {
        return new Tuple<T1, T2>(t1, t2);
    }
    //etc...
}

هناك سليم (ليس سريعا) C # الصفوف التنفيذ في مكتبات لوكاد المشتركة (مفتوح المصدر بالطبع) يتضمن الميزات المطلوبة التالية:

  • 2-5 تطبيقات Tuple غير قابلة للتغيير
  • DebuggerDisplayAttribute الصحيح
  • التجزئة الصحيحة والتحقق من المساواة
  • أدوات مساعدة لإنشاء صفوف من المعلمات المتوفرة (يتم استنتاج الأدوية العامة بواسطة المترجم) وامتدادات للعمليات القائمة على المجموعة.
  • تم اختبار الإنتاج.

إن تنفيذ فئات Tuple أو إعادة استخدام فئات F# داخل C# هو نصف القصة فقط - فهي تمنحك القدرة على إنشاء صفوف بسهولة نسبية، ولكنها ليست في الحقيقة السكر النحوي الذي يجعلها لطيفة جدًا للاستخدام في لغات مثل F#.

على سبيل المثال، في F#، يمكنك استخدام مطابقة النمط لاستخراج كلا الجزأين من الصف ضمن بيان Let، على سبيل المثال

let (a, b) = someTupleFunc

لسوء الحظ، فإن القيام بنفس الشيء باستخدام فئات F# من لغة C# سيكون أقل أناقة بكثير:

Tuple<int,int> x = someTupleFunc();
int a = x.get_Item1();
int b = x.get_Item2();

تمثل Tuples طريقة قوية لإرجاع قيم متعددة من استدعاء دالة دون الحاجة إلى تناثر التعليمات البرمجية الخاصة بك بفئات مهملة، أو اللجوء إلى مرجع قبيح أو معلمات خارجية.ومع ذلك، في رأيي، بدون بعض السكر النحوي لجعل إنشائها والوصول إليها أكثر أناقة، فهي ذات فائدة محدودة.

في رأيي، ميزة الأنواع المجهولة ليست صفًا، ولكنها بنية مشابهة جدًا.إن مخرجات بعض استعلامات LINQ عبارة عن مجموعات من الأنواع المجهولة، والتي تتصرف مثل الصفوف.

فيما يلي عبارة تنشئ صفًا مكتوبًا :-) سريعًا:

var p1 = new {a = "A", b = 3};

يرى: http://www.developer.com/net/csharp/article.php/3589916

يدعم C#7 الصفوف أصلاً:

var unnamedTuple = ("Peter", 29);
var namedTuple = (Name: "Peter", Age: 29);
(string Name, double Age) typedTuple = ("Peter", 29);

بلدي مفتوح المصدر .NET مكتبة ساسا يحتوي على صفوف لسنوات (إلى جانب الكثير من الوظائف الأخرى، مثل تحليل MIME الكامل).لقد كنت أستخدمه في كود الإنتاج منذ بضع سنوات جيدة حتى الآن.

يدعم C# الصفوف البسيطة عبر الأدوية العامة بسهولة تامة (وفقًا لإجابة سابقة)، ومع "الكتابة الغامضة" (واحدة من العديد من التحسينات الممكنة للغة C#) لتحسين استنتاج النوع، يمكن أن تكون قوية جدًا جدًا.

مقابل ما يستحق، يدعم F# الصفوف أصلاً، وبعد اللعب بها، لست متأكدًا من أن الصفوف (المجهولة) تضيف الكثير...ما تكسبه في الإيجاز تخسره جداً بسرعة في وضوح الكود.

بالنسبة للتعليمات البرمجية ضمن طريقة واحدة، هناك أنواع مجهولة؛بالنسبة للكود الذي يخرج عن الطريقة، أعتقد أنني سألتزم بالأنواع المسماة البسيطة.بالطبع، إذا كانت لغة C# المستقبلية تجعل من السهل جعل هذه الأشياء غير قابلة للتغيير (مع سهولة العمل معها) سأكون سعيدًا.

هذه هي مجموعتي من الصفوف، التي يتم إنشاؤها تلقائيًا بواسطة برنامج Python النصي، لذلك ربما أكون قد بالغت قليلاً:

رابط إلى مستودع التخريب

ستحتاج إلى اسم مستخدم/كلمة مرور، كلاهما ضيف

إنهم يعتمدون على الميراث، ولكن Tuple<Int32,String> لن تقارن على قدم المساواة ل Tuple<Int32,String,Boolean> حتى لو كان لديهم نفس القيم للعضوين الأولين.

كما يقومون أيضًا بتنفيذ GetHashCode وToString وما إلى ذلك، والكثير من أساليب المساعدة الصغيرة.

مثال للاستخدام:

Tuple<Int32, String> t1 = new Tuple<Int32, String>(10, "a");
Tuple<Int32, String, Boolean> t2 = new Tuple<Int32, String, Boolean>(10, "a", true);
if (t1.Equals(t2))
    Console.Out.WriteLine(t1 + " == " + t2);
else
    Console.Out.WriteLine(t1 + " != " + t2);

سوف الإخراج:

10, a != 10, a, True

إذا كنت أتذكر دروس علوم الكمبيوتر الخاصة بي بشكل صحيح، فإن الصفوف هي مجرد بيانات.

إذا كنت تريد بيانات مجمعة - قم بإنشاء فئات تحتوي على خصائص.إذا كنت بحاجة إلى شيء مثل KeyValuePair ثم ها هو.

سأكون متفاجئًا - لغة C# هي لغة مكتوبة بقوة، في حين أن الصفوف (tuples) مناسبة للغات المكتوبة بشكل أكثر ديناميكية.لقد أصبحت لغة #C تنجرف بشكل أكثر ديناميكية مع مرور الوقت، ولكن هذا يعتبر سكرًا نحويًا، وليس تحولًا حقيقيًا في أنواع البيانات الأساسية.

إذا كنت تريد قيمتين في حالة واحدة، فإن KeyValuePair<> هو بديل لائق، وإن كان أخرق.يمكنك أيضًا إنشاء بنية أو فئة تقوم بنفس الشيء، وتكون قابلة للتوسيع.

لجعلها مفيدة في جدول التجزئة أو القاموس، من المحتمل أنك تريد توفير التحميل الزائد لـ GetHashCode و Equals.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top