سؤال

هل يمكنني تعيين كل قيمة في صفيف لفصل المتغيرات في سطر واحد في C#؟إليك مثال في كود روبي لما أريد:

irb(main):001:0> str1, str2 = ["hey", "now"]
=> ["hey", "now"]
irb(main):002:0> str1
=> "hey"
irb(main):003:0> str2
=> "now"

لست متأكدًا مما إذا كان ما أريده ممكنًا في C#.

يحرر: بالنسبة لأولئك الذين يقترحون تعيين السلاسل "مرحبًا" و"الآن" للمتغيرات، فهذا ليس ما أريده.تخيل ما يلي:

irb(main):004:0> val1, val2 = get_two_values()
=> ["hey", "now"]
irb(main):005:0> val1
=> "hey"
irb(main):006:0> val2
=> "now"

الآن حقيقة أن الطريقة get_two_values السلاسل التي تم إرجاعها "مرحبًا" و"الآن" هي أمر تعسفي.في الواقع، يمكنها إرجاع أي قيمتين، ولا يجب أن تكونا سلاسل.

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

المحلول

هذا غير ممكن في C#.

أقرب شيء يمكنني التفكير فيه هو استخدام التهيئة بنفس السطر مع الفهارس

strArr = new string[]{"foo","bar"};
string str1 = strArr[0], str2 = strArr[1];

نصائح أخرى

تحديث: في C#7، يمكنك بسهولة تعيين متغيرات متعددة مرة واحدة باستخدام الصفوف.لتعيين عناصر المصفوفة للمتغيرات، ستحتاج إلى كتابة دالة مناسبة Deconstruct() طرق التمديد:

هناك طريقة أخرى لاستهلاك الصفوف وهي تفكيكها.إعلان تفكيك هو بناء جملة لتقسيم tuple (أو قيمة أخرى) في أجزائه وتعيين هذه الأجزاء بشكل فردي للمتغيرات الجديدة:

(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
WriteLine($"found {first} {last}.");

في إعلان تفكيك ، يمكنك استخدام VAR للمتغيرات الفردية المعلنة:

(var first, var middle, var last) = LookupName(id1); // var inside

أو حتى وضع var واحد خارج الأقواس كاختصار:

var (first, middle, last) = LookupName(id1); // var outside

يمكنك أيضًا تفكيك المتغيرات الموجودة مع مهمة تفكيك:

(first, middle, last) = LookupName(id2); // deconstructing assignment

التفكيك ليس فقط للصفوف.يمكن تفكيك أي نوع ، طالما أنه يحتوي على طريقة تفكيك (مثيل أو تمديد) للنموذج:

public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }

The out parameters constitute the values that result from the deconstruction.

(لماذا يستخدم المعلمات بدلاً من إرجاع الصف؟هذا بحيث يمكنك الحصول على العديد من الأحمال الزائدة لأرقام مختلفة من القيم).

class Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) { X = x; Y = y; }
    public void Deconstruct(out int x, out int y) { x = X; y = Y; }
}

(var myX, var myY) = GetPoint(); // calls Deconstruct(out myX, out myY);

سيكون نمطًا شائعًا أن يكون المُنشئون والفكات "متماثلًا" بهذه الطريقة. https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/


الجواب القديم:

في الواقع، يمكنك تحقيق وظائف مماثلة في C# باستخدام طرق الامتداد مثل هذه (ملاحظة:لم أقم بتضمين التحقق مما إذا كانت الوسائط صالحة):

public static void Match<T>(this IList<T> collection, Action<T,T> block)
{
    block(collection[0], collection[1]);
}
public static void Match<T>(this IList<T> collection, Action<T,T,T> block)
{
    block(collection[0], collection[1], collection[2]);
}
//...

ويمكنك استخدامها مثل هذا:

new[] { "hey", "now" }.Match((str1, str2) =>
{
    Console.WriteLine(str1);
    Console.WriteLine(str2);
});

في حالة الحاجة إلى قيمة إرجاع من دالة، سيعمل التحميل الزائد التالي:

public static R Match<T,R>(this IList<T> collection, Func<T, T, R> block)
{
    return block(collection[0], collection[1]);
}

private string NewMethod1()
{   
    return new[] { "hey", "now" }.Match((str1, str2) =>
    {
        return str1 + str2;
    });
}

في هذا الطريق:

  • يمكنك تجنب الاضطرار إلى تكرار اسم المصفوفة كما هو الحال في الحل الذي اقترحه JaredPar وآخرون؛قائمة "المتغيرات" سهلة القراءة.

  • أنت تتجنب الاضطرار إلى الإعلان بشكل صريح عن أنواع المتغيرات كما هو الحال في حل Daniel Earwicker.

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

أعلم أنه سؤال عمره 7 سنوات، ولكن منذ وقت ليس ببعيد كنت بحاجة إلى مثل هذا الحل - من السهل إعطاء أسماء لعناصر المصفوفة التي تم تمريرها إلى الطريقة (لا، استخدام الفئات/البنيات بدلاً من المصفوفات لم يكن عمليًا، لأنه بالنسبة للمصفوفات نفسها قد أحتاج إلى أسماء عناصر مختلفة بطرق مختلفة) ولسوء الحظ انتهى بي الأمر برمز مثل هذا:

var A = points[0];
var A2 = points[1];
var B = points[2];
var C2 = points[3];
var C = points[4];

الآن يمكنني أن أكتب (في الواقع، لقد قمت بإعادة هيكلة إحدى هذه الطرق الآن!):

points.Match((A, A2, B, C2, C) => {...});

يشبه الحل الخاص بي مطابقة الأنماط في F# وقد ألهمتني هذه الإجابة: https://stackoverflow.com/a/2321922/6659843

حالة الاستخدام الواقعية لذلك هي توفير طريقة مناسبة لإرجاع قيم متعددة من دالة.لذا فهي دالة روبي تقوم بإرجاع عدد ثابت من القيم في المصفوفة، ويريدها المتصل في متغيرين منفصلين.هذا هو المكان الذي تكون فيه الميزة أكثر منطقية:

first_name, last_name = get_info() // always returns an array of length 2

للتعبير عن هذا في C#، يمكنك وضع علامة على المعلمتين out في تعريف الطريقة، والعودة void:

public static void GetInfo(out string firstName, out string lastName)
{
    // assign to firstName and lastName, instead of trying to return them.
}

وهكذا نسميها:

string firstName, lastName;
SomeClass.GetInfo(out firstName, out lastName);

انها ليست لطيفة جدا.نأمل أن تسمح بعض الإصدارات المستقبلية من C# بهذا:

var firstName, lastName = SomeClass.GetInfo();

لتمكين هذا، GetInfo ستعيد الطريقة أ Tuple<string, string>.سيكون هذا تغييرًا غير منقطع في اللغة مثل الاستخدامات القانونية الحالية لـ var مقيدة للغاية لذا لا يوجد استخدام صالح حتى الآن لصيغة "الإعلان المتعدد" المذكورة أعلاه.

يمكنك القيام بذلك في سطر واحد، ولكن ليس في عبارة واحدة.

على سبيل المثال:

int str1 = "hey"; int str2 = "now";

تدعم بايثون وروبي المهمة التي تحاول القيام بها؛C # لا.

لست متأكدًا مما إذا كان ما أريده ممكنًا في C#.

ليست كذلك.

يمكنك القيام بذلك في C#

string str1 = "hey", str2 = "now";

أو يمكنك أن تكون يتوهم مثل هذا

        int x, y;
        int[] arr = new int[] { x = 1, y = 2 };

لا، ولكن يمكنك تهيئة مجموعة من السلاسل:

string[] strings = new string[] {"hey", "now"};

على الرغم من أن هذا ربما لا يكون مفيدًا جدًا بالنسبة لك.بصراحة ليس من الصعب وضعها في سطرين:

string str1 = "hey";
string str2 = "now";

يمكنك استخدام الصفوف المسماة مع ج#7 الآن.

{
  (string part1, string part2) = Deconstruct(new string[]{"hey","now"});
}

public (string, string) Deconstruct(string[] parts)
{
   return (parts[0], parts[1]);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top