type-inference اكواد - استخدام الكلمة الرئيسية var في C#




عربي بلغة (25)

For the afficionados that think var saves time, it takes less keystrokes to type:

StringBuilder sb = new StringBuilder();

من

var sb = new StringBuilder();

Count em if you don't believe me...

19 versus 21

I'll explain if I have to, but just try it... (depending on the current state of your intellisense you may have to type a couple more for each one)

And it's true for every type you can think of!!

My personal feeling is that var should never be used except where the type is not known because it reduces recognition readabiltiy in code. It takes the brain longer to recognize the type than a full line. Old timers who understand machine code and bits know exactly what I am talking about. The brain processes in parallel and when you use var you force it to serialize its input. Why would anyone want to make their brain work harder? That's what computers are for.

بعد مناقشة مع الزملاء فيما يتعلق باستخدام الكلمة الرئيسية "var" في C # 3 ، تساءلت ما هي آراء الناس حول الاستخدام المناسب للاستدلال النوعي عبر var؟

على سبيل المثال ، أنا استعملت على نحو فوضوي في ظروف مشكوك فيها ، على سبيل المثال: -

foreach(var item in someList) { // ... } // Type of 'item' not clear.
var something = someObject.SomeProperty; // Type of 'something' not clear.
var something = someMethod(); // Type of 'something' not clear.

الاستخدامات الأكثر شرعية لـ var هي كالتالي:

var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.

من المثير للاهتمام أن LINQ يبدو قليلاً من مساحة رمادية ، على سبيل المثال: -

var results = from r in dataContext.SomeTable
              select r; // Not *entirely clear* what results will be here.

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

إنه أسوأ حتى عندما يتعلق الأمر LINQ إلى الأشياء ، على سبيل المثال: -

var results = from item in someList
              where item != 3
              select item;

هذا ليس أفضل من equeachent foreach (var item in someList) {// ...} equivilent.

هناك قلق حقيقي حول سلامة النوع هنا - على سبيل المثال ، إذا كنا سنضع نتائج هذا الاستعلام في طريقة فوق طاقتها تقبل IEnumerable <int> و IEnumerable <double> قد يمرر المتصل دون قصد في النوع الخاطئ.

لا يحتفظ var بكتابة قوية ولكن السؤال هو في الحقيقة ما إذا كان من الخطير أن لا يكون هذا النوع ظاهرًا على الفور في التعريف ، وهو أمر يتم تضخيمه عندما تعني الحمولة الزائدة أن أخطاء المترجم قد لا يتم إصدارها عند تمرير نوع الخطأ بطريقة غير مقصودة إلى طريقة ما.


Stolen from the post on this issue at CodingHorror :

Unfortunately, you and everyone else pretty much got it wrong. While I agree with you that redundancy is not a good thing, the better way to solve this issue would have been to do something like the following:

MyObject m = new();

Or if you are passing parameters:

Person p = new("FirstName", "LastName);

Where in the creation of a new object, the compiler infers the type from the left-hand side, and not the right. This has other advantages over "var", in that it could be used in field declarations as well (there are also some other areas that it could be useful as well, but I won't get into it here).

In the end, it just wasn't intended to reduce redundancy. Don't get me wrong, "var" is VERY important in C# for anonymous types/projections, but the use here is just WAY off (and I've been saying this for a long, long time) as you obfuscate the type that is being used. Having to type it twice is too often, but declaring it zero times is too few.

Nicholas Paldino .NET/C# MVP on June 20, 2008 08:00 AM

I guess if your main concern is to have to type less -- then there isn't any argument that's going to sway you from using it.

If you are only going to ever be the person who looks at your code, then who cares? Otherwise, in a case like this:

var people = Managers.People

it's fine, but in a case like this:

var fc = Factory.Run();

it short circuits any immediate type deductions my brain could begin forming from the 'English' of the code.

Otherwise, just use your best judgment and programming 'courtesy' towards others who might have to work on your project.


I guess it depends on your perspective. I personally have never had any difficulty understanding a piece of code because of var "misuse", and my coworkers and I use it quite a lot all over. (I agree that Intellisense is a huge aid in this regard.) I welcome it as a way to remove repetitive cruft.

After all, if statements like

var index = 5; // this is supposed to be bad

var firstEligibleObject = FetchSomething(); // oh no what type is it
                                            // i am going to die if i don't know

were really that impossible to deal with, nobody would use dynamically typed languages.


I only use var when it's clear to see what type is used.

For example, I would use var in this case, because you can see immediately that x will be of the type "MyClass":

var x = new MyClass();

I would NOT use var in cases like this, because you have to drag the mouse over the code and look at the tooltip to see what type MyFunction returns:

var x = MyClass.MyFunction();

Especially, I never use var in cases where the right side is not even a method, but only a value:

var x = 5;

(because the compiler can't know if I want a byte, short, int or whatever)


لا أرى ما هي الصفقة الكبيرة

var something = someMethod(); // Type of 'something' not clear <-- not to the compiler!

لا يزال لديك انتفاضة كاملة على "شيء ما" ، وبالنسبة لأي حالة غامضة لديك اختبارات الوحدة الخاصة بك ، أليس كذلك؟ ( هل؟ )

انها ليست varchar ، انها ليست قاتمة ، وبالتأكيد ليست دينامية أو ضعيفة الكتابة. إنه يوقف المجانين مثل هذا:

List<somethinglongtypename> v = new List<somethinglongtypename>();

وخفض مجموع العقل الكلي إلى:

var v = new List<somethinglongtypename>();

لطيفة ، ليست لطيفة تمامًا مثل:

v = List<somethinglongtypename>();

ولكن هذا هو ما يعتبره Boo .


إذا كان شخص ما يستخدم الكلمة الرئيسية var لأنها لا تريد "معرفة النوع" ، فهذا بالتأكيد هو السبب الخاطئ. لا تُنشئ الكلمة الرئيسية var متغيرًا ذا نوع ديناميكي ، فما زال المحول البرمجي بحاجة إلى معرفة النوع. بما أن المتغير يحتوي دائمًا على نوع محدد ، فيجب أن يكون النوع أيضًا واضحًا في الكود إن أمكن.

الأسباب الجيدة لاستخدام الكلمة الرئيسية var هي على سبيل المثال:

  • حيث يكون مطلوبًا ، أي إعلان مرجع لنوع مجهول.
  • حيث يجعل الشفرة أكثر قابلية للقراءة ، أي إزالة الإعلانات التكرارية.

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



أﻋﺗﻘد أن اﻟﺷﻲء اﻟرﺋﯾﺳﻲ ﻣﻊ VAR ھو اﺳﺗﺧداﻣﮫ ﻓﻘط ﻋﻧدﻣﺎ ﯾﮐون ﻣﻧﺎﺳﺑًﺎ ، أي ﻋﻧد اﻟﻘﯾﺎم ﺑﻌﻣﻟﯾﺎت ﻓﻲ Linq ﯾﺳﮭﻟﮭﺎ (ورﺑﻣﺎ ﻓﻲ ﺣﺎﻻت أﺧرى).

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

إن الحظر الشامل سيء مثل إساءة استخدام البناء في المقام الأول ولكن هناك حاجة إلى أن يكون معيارًا معقولًا للتشفير.

والشيء الآخر الذي يجب تذكره هو أن نوع VB الخاص به لا يتغير من حيث أنه لا يستطيع تغيير أنواعه - إنه متغير تم كتابته بشكل كبير فقط لأن هذا النوع من الاستدلال (وهذا هو السبب في وجود أشخاص يجادلون أنه ليس من غير المعقول أن استخدمها في ، على سبيل المثال ، foreach لكنني لا أوافق على أسباب قابلية القراءة والصيانة.

أظن أن هذا سوف يتم تشغيله وتشغيله (-:

مورفي


To me, the antipathy towards var illustrates why bilingualism in .NET is important. To those C# programmers who have also done VB .NET, the advantages of var are intuitively obvious. The standard C# declaration of:

List<string> whatever = new List<string>();

is the equivalent, in VB .NET, of typing this:

Dim whatever As List(Of String) = New List(Of String)

Nobody does that in VB .NET, though. It would be silly to, because since the first version of .NET you've been able to do this...

Dim whatever As New List(Of String)

...which creates the variable and initializes it all in one reasonably compact line. Ah, but what if you want an IList<string> , not a List<string> ? Well, in VB .NET that means you have to do this:

Dim whatever As IList(Of String) = New List(Of String)

Just like you'd have to do in C#, and obviously couldn't use var for:

IList<string> whatever = new List<string>();

If you need the type to be something different, it can be. But one of the basic principles of good programming is reducing redundancy, and that's exactly what var does.


@aku: One example is code reviews. Another example is refactoring scenarios.

Basically I don't want to go type-hunting with my mouse. It might not be available.


فار ، في رأيي ، في C # هو شيء جيد TM . لا يزال أي متغير مكتوب عليه مكتوبًا بقوة ، ولكنه يحصل على نوعه من الجانب الأيمن من المهمة حيث يتم تعريفه. ونظرًا لأن معلومات النوع متاحة على الجانب الأيسر ، ففي معظم الحالات ، يكون من الضروري إضافة مطوّل مفرط لإدخالها على الجانب الأيمن. أعتقد أن هذا يزيد من إمكانية القراءة بشكل ملحوظ دون تقليل سلامة النوع.

من وجهة نظري ، استخدام اصطلاحات التسمية الجيدة للمتغيرات والطرق أكثر أهمية من منظور قابلية القراءة من معلومات النوع الواضح. إذا احتجت إلى معلومات النوع ، فيمكنني دائمًا التحويم فوق المتغير (في VS) والحصول عليه. بشكل عام ، على الرغم من ذلك ، لا يجب أن تكون معلومات الكتابة الصريحة ضرورية للقارئ. بالنسبة للمطور ، في VS لا تزال تحصل على Intellisense ، بغض النظر عن كيفية الإعلان عن المتغير. بعد قول كل ذلك ، قد لا تزال هناك حالات يكون فيها من المنطقي أن تعلن صراحةً النوع - ربما لديك طريقة تقوم بإرجاع List<T> ، ولكنك تريد معاملتها كـ IEnumerable<T> في طريقة. للتأكد من أنك تستخدم الواجهة ، فإن تحديد متغير لنوع الواجهة قد يجعل ذلك صريحًا. أو ربما ترغب في إعلان متغير بدون قيمة أولية - لأنه يحصل على قيمة مباشرة على أساس شرط ما. في هذه الحالة تحتاج إلى النوع. إذا كانت معلومات النوع مفيدة أو ضرورية ، فانتقل إليها واستخدمها. على الرغم من ذلك ، أشعر أنه من غير الضروري أن تكون الشفرة أسهل في القراءة في معظم الحالات.


الوقت الأكثر احتمالا ستحتاج إلى هذا هو لأنواع المجهولين (حيث هو مطلوب 100 ٪) ؛ ولكنه أيضًا يتجنب التكرار للحالات التافهة ، وتصبح المنظمة البحرية الدولية الخط أكثر وضوحًا. لست بحاجة إلى رؤية النوع مرتين للتهيئة البسيطة.

فمثلا:

Dictionary<string, List<SomeComplexType<int>>> data = new Dictionary<string, List<SomeComplexType<int>>>();

(من فضلك لا تقم بتحرير hscroll في أعلاه - فإنه يثبت نقطة!)

ضد:

var data = new Dictionary<string, List<SomeComplexType<int>>>();

ومع ذلك ، هناك حالات يكون فيها هذا مضللاً ، ويمكن أن يتسبب في حدوث أخطاء. كن حذراً باستخدام var إذا كان المتغير الأصلي والنوع المبدئي غير متطابقين. فمثلا:

static void DoSomething(IFoo foo) {Console.WriteLine("working happily") }
static void DoSomething(Foo foo) {Console.WriteLine("formatting hard disk...");}

// this working code...
IFoo oldCode = new Foo();
DoSomething(oldCode);
// ...is **very** different to this code
var newCode = new Foo();
DoSomething(newCode);

لقد اعتمدنا "رمز للأشخاص ، وليس الآلات" ، على أساس افتراض أنك تقضي عدة مرات في وضع الصيانة أكثر من التطوير الجديد.

بالنسبة لي ، تستبعد الحجة القائلة بأن المحول البرمجي "يعرف" ما هو نوع المتغير - بالتأكيد ، لا يمكنك كتابة رمز غير صالح في المرة الأولى لأن المحول البرمجي يوقف شفرتك من التجميع ، ولكن عندما يقرأ المطور التالي الشفرة في غضون 6 أشهر ، يجب أن يكونوا قادرين على استنتاج ما يفعله المتغير بشكل صحيح أو غير صحيح وتحديد سبب القضايا بسرعة.

وهكذا،

var something = SomeMethod();

تم حظره وفقًا لمعايير الترميز ، ولكن يتم تشجيع ما يلي في فريقنا لأنه يزيد من سهولة القراءة:

var list = new List<KeyValuePair<string, double>>();
FillList( list );
foreach( var item in list ) {
   DoWork( item ); 
}

It can certainly make things simpler, from code I wrote yesterday:

var content  = new Queue<Pair<Regex, Func<string, bool>>>();
...
foreach (var entry in content) { ... }

This would have be extremely verbose without var .

Addendum: A little time spent with a language with real type inference (eg F#) will show just how good compilers are at getting the type of expressions right. It certainly has meant I tend to use var as much as I can, and using an explicit type now indicates that the variable is not of the initialising expression's type.


بالتأكيد ، int سهلة ، ولكن عندما يكون نوع المتغير هو IEnumerable<MyStupidLongNamedGenericClass<int, string>> ، var يجعل الأمور أسهل بكثير.


Use it for anonymous types - that's what it's there for. Anything else is a use too far. Like many people who grew up on C, I'm used to looking at the left of the declaration for the type. I don't look at the right side unless I have to. Using var for any old declaration makes me do that all the time, which I personally find uncomfortable.

Those saying 'it doesn't matter, use what you're happy with' are not seeing the whole picture. Everyone will pick up other people's code at one point or another and have to deal with whatever decisions they made at the time they wrote it. It's bad enough having to deal with radically different naming conventions, or - the classic gripe - bracing styles, without adding the whole ' var or not' thing into the mix. The worst case will be where one programmer didn't use var and then along comes a maintainer who loves it, and extends the code using it. So now you have an unholy mess.

Standards are a good thing precisely because they mean you're that much more likely to be able to pick up random code and be able to grok it quickly. The more things that are different, the harder that gets. And moving to the 'var everywhere' style makes a big difference.

I don't mind dynamic typing, and I don't mind implict typing - in languages that are designed for them. I quite like Python. But C# was designed as a statically explicitly-typed language and that's how it should stay. Breaking the rules for anonymous types was bad enough; letting people take that still further and break the idioms of the language even more is something I'm not happy with. Now that the genie is out of the bottle, it'll never go back in. C# will become balkanised into camps. Not good.


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

باعتراف الجميع ، قد يعني ذلك أنه ليس من الواضح ما هو النوع الذي نتعامل معه. وماذا في ذلك؟ هذا هو في الواقع نقطة التصميم المنفصل. عند التعامل مع الواجهات ، فأنت لا تهتم بشكل قاطع بالنوع الذي يحتويه المتغير. يأخذ var أكثر من ذلك بكثير ، صحيح ، لكني أعتقد أن الحجة تبقى كما هي من وجهة نظر قابلية القراءة: لا ينبغي للمبرمج أن يكون مهتمًا بالفعل بنوع المتغير ، بل بالأحرى ما يفعله المتغير. ولهذا السبب تقوم Microsoft أيضًا بالاتصال باستدعاء الكتابة "كتابة بطة".

لذا ، ماذا يفعل المتغير عندما أعلن عنه باستخدام var ؟ سهل ، يفعل أي شيء يخبرني IntelliSense أنه يفعل. أي منطق عن C # يتجاهل IDE يقصر عن الواقع. في الممارسة ، يتم برمجة كل رمز C # في IDE يعتمد IntelliSense.

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

الآن ، أصدر فريق C # توجيهًا ترميزًا ينص على أنه يجب استخدام var فقط للحصول على نتيجة عبارة LINQ التي تنشئ نوعًا مجهولاً (لأن هنا ، ليس لدينا بديل حقيقي لـ var ). حسنا ، هذا المسمار. طالما أن فريق C # لا يعطيني حجة سليمة لهذا المبدأ التوجيهي ، فسوف أتجاهله لأنه برأيي المهني والشخصي ، إنه هراء خالص. (عذرا ؛ ليس لدي أي رابط للمبدأ التوجيهي المعني.)

في الواقع ، هناك بعض التفسيرات الجيدة (السطحية) حول سبب عدم استخدام var لكن ما زلت أعتقد أنها خاطئة إلى حد كبير. لنأخذ مثال "البحث": يدعي المؤلف أن var يصعّب البحث عن أماكن تستخدم فيها MyType . حق. تفعل ذلك واجهات. في الواقع ، لماذا أرغب في معرفة مكان استخدام الفصل؟ قد أكون أكثر اهتماما في المكان الذي يتم إنشاءه وسيظل هذا البحث قابلا للبحث لأنه في مكان ما يجب أن يتم استدعاء منشئه (حتى إذا تم ذلك بطريقة غير مباشرة ، يجب ذكر اسم النوع في مكان ما).


أعتقد أن استخدام var يجب أن يقترن بأسماء المتغيرات المختارة بحكمة.

ليس لدي أي مشكلة في استخدام var في عبارة foreach ، بشرط ألا يكون هذا كما يلي:

foreach (var c in list) { ... }

لو كان أكثر مثل هذا:

foreach (var customer in list) { ... }

... سيكون من المحتمل جدًا أن يفهم شخص ما قراءة الشفرة ما هي "القائمة". إذا كنت تتحكم في اسم متغير القائمة نفسه ، فهذا أفضل.

ويمكن أن ينطبق الشيء نفسه على حالات أخرى. هذا غير مفيد

var x = SaveFoo(foo);

... لكن هذا منطقي:

var saveSucceeded = SaveFoo(foo);

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

var f = (float)3;

أحتاج إلى نوع من برنامج var-12-step. اسمي مات ، وأنا (أ ب) استخدام فار.


من إريك ليبرت ، مهندس تصميم برامج أقدم في فريق C #:

لماذا تم إدخال الكلمة الرئيسية var ؟

هناك سببان ، أحدهما موجود اليوم ، والذي سيظهر في 3.0.

السبب الأول هو أن هذا الرمز قبيح بشكل لا يصدق بسبب كل التكرار:

Dictionary<string, List<int>> mylists = new Dictionary<string, List<int>>();

وهذا مثال بسيط - لقد كتبت أسوأ. في أي وقت تضطر فيه إلى كتابة نفس الشيء مرتين ، فهذا تكرار يمكن أن نزيله. أجمل كثيرا للكتابة

var mylists = new Dictionary<string,List<int>>();

ودع الرقم المترجم يخرج ما يعتمد عليه النوع على الاحالة.

ثانيا ، يقدم C # 3.0 أنواع مجهولة. بما أن الأنواع المجهولة بالتعريف ليس لها أسماء ، يجب أن تكون قادراً على استنتاج نوع المتغير من تعبير التهيئة إذا كان نوعه مجهولاً.

التركيز لي. لا تزال المادة كاملة ، C # 3.0 مكتوبة بشكل ثابت ، صادقة! ، series التي تلت ذلك هي جيدة جدا.

هذا هو ما هو var . استخدامات أخرى ربما لن تعمل بشكل جيد. أي مقارنة إلى JScript أو VBScript أو الكتابة الديناميكية هو إجمالي غير صحيح. لاحظ مرة أخرى ، var مطلوب لكي تعمل بعض الميزات الأخرى في .NET.


Many time during testing, I find myself having code like this:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();
Console.WriteLine(something);

Now, sometimes, I'll want to see what the SomeOtherThing itself contains, SomeOtherThing is not the same type that CallMethod() returns. Since I'm using var though, I just change this:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();

الى هذا:

var something = myObject.SomeProperty.SomeOtherThing;

Without var, I'd have to keep changing the declared type on the left hand side as well. I know it's minor, but it's extremely convenient.


It's a matter of taste. All this fussing about the type of a variable disappears when you get used to dynamically typed languages. That is, if you ever start to like them (I'm not sure if everybody can, but I do).

C#'s var is pretty cool in that it looks like dynamic typing, but actually is static typing - the compiler enforces correct usage.

The type of your variable is not really that important (this has been said before). It should be relatively clear from the context (its interactions with other variables and methods) and its name - don't expect customerList to contain an int ...

I am still waiting to see what my boss thinks of this matter - I got a blanket "go ahead" to use any new constructs in 3.5, but what will we do about maintenance?


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

حالة أخرى مثيرة للقلق ، في المكالمة التالية لا يمكنك معرفة فقط من خلال النظر إلى رمز نوع عاد بواسطة CallMe :

var variable = CallMe();

هذا هو شكوى بلدي الرئيسي ضد فار.

أستخدم var عندما أعلن المفوضين المجهولين في الطرق ، وبصورة ما يبدو var أنظف مما لو كنت أستخدم Func . خذ بعين الاعتبار هذا الرمز:

var callback = new Func<IntPtr, bool>(delegate(IntPtr hWnd) {
   ...
});

تعديل: تحديث نموذج التعليمات البرمجية الأخير استناداً إلى إدخال Julian


حالة واحدة محددة حيث يكون var صعبًا: مراجعات الشفرة غير المتصلة ، وخاصة تلك التي يتم تنفيذها على الورق.

لا يمكنك الاعتماد على الماوس الفأر لذلك.


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

إذا كان لديك سطر من التعليمات البرمجية مثل

IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

هل أسهل أو أصعب في القراءة من:

var nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

سوف أستفيد من ميزة .NET 4.0+ وأقدم إجابة محدثة للواجهة المقبولة في الأصل:

foreach(var entry in MyDic)
{
    // do something with entry.Value or entry.Key
}




c# type-inference var