18

Our coding standards ask that we minimise the use of C# var (suggests limiting it's use to being in conjunction with Linq). However there are times when using generics where it's reasonably convenient e.g.

Dictionary<DateTime, Dictionary<string, float>> allValues = ...
// ...
foreach (var dateEntry in allValue)

is easier to type

foreach (KeyValue<DateTime, Dictionary<string, float>> dateEntry in allValue) 

(and easier than remembering what the explicit type is in some cases).

Do any of the refactoring tools have the ability to convert the former to the latter. I've had a look at Resharper but it doesn't seem to do (indeed it's default suggestion is to go in the opposite direction).

Ian G
  • 10,709
  • 6
  • 30
  • 34

7 Answers7

19

I've got ReSharper 4.1, and it does offer this option (in either direction).

Actually, I'd recommend challenging the standard... the former is far more readable than the latter (especially if you call the variable pair or something similar). I would't use "var" for var i = 0, but it is ideally suited to the above.

For bulk changing, go to:

  • Cleanup Code... (pick a profile => "Edit Profiles" => Tools => Code Cleanup)
    • C#
      • Use 'var' in declaration
        • Replace direction = Can 'var' to type usage
        • 'foreach' iterator declaration style = Always use explicit type
        • Local variable declaration style = Always use explicit type

and run...

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
16

This is possible in Visual Studio 2017.

Tools > Options > Text Editor > C# > Code Style > General –

Find 'var' preferences > When variable type is apparent. For Preference select "Prefer explicit type," and for Severity select "Suggestion."

enter image description here

You'll now get the light bulb actions when you use var, and you can quickly change to the explicit type by using the Ctrl. shortcut key.

enter image description here

enter image description here

HaveSpacesuit
  • 3,572
  • 6
  • 40
  • 59
  • Somehow this isn't working for me after changing the suggested settings? The only option I have in the lightbulb is 'Extract Method'? I'm using Visual Studio 2017 CE... Is there any other option needed to get this working? – Run CMD Feb 21 '18 at 14:49
  • 1
    I'm not sure about Community Edition, but I wouldn't expect it to be different. Try setting the severity to warning or exception and see if it shows in your Error List. Maybe also try restarting VS? – HaveSpacesuit Feb 21 '18 at 15:24
  • Changing the severity to Warning or Error does work, Thanks for the tip!! – Run CMD Feb 21 '18 at 15:46
4

Resharper does this (only in version 4+ I'm sure of it) but I don't know if its possible to simply convert var into the specific type automatic - eventually you need to go to the "var" and then a light shows up which gives you the option to specify the type explicitly

Bluenuance
  • 4,813
  • 4
  • 23
  • 19
3

@Adam - you can't declare a class here, since that won't be what comes back from an IDictionary<,>.GetEnumerator() - however, you can alias via using:

using InnerPair = System.Collections.Generic.KeyValuePair<System.DateTime,
    System.Collections.Generic.Dictionary<string, float>>;

Then:

foreach(InnerPair pair in dict) {...}

This is just a type alias, so works fine.

Community
  • 1
  • 1
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
3

DevExpress supports this with CodeRush, and they recently starting giving some of the refactorings away for free. The refactoring you are looking for is "Make Explicit"

http://devexpress.com/Products/Visual_Studio_Add-in/CodeRushX/

Bob
  • 97,670
  • 29
  • 122
  • 130
3

May be very late, but I wrote a Visual Studio 2015 extension that does this based on .NET Compiler platform. Replace var with Type It is tested for normal scenarios and if there is a bug, I shall fix it at the earliest and its also open source in case someone wants to contribute or enhance this tool.

Rishabh Verma
  • 117
  • 2
  • 9
0

I'd argue that where you have complex generic types on your domain objects you should typedef them

class DomainValueCollection : KeyValue<DateTime, Dictionary<string, float>>{}

where DomainValueCollection is somehting that makes sense in your domain context

the code then becomes

var allItems = new DomainValueCollection();

rather than

var allItems = new KeyValue<DateTime, Dictionary<string, float>>();
Adam Straughan
  • 2,766
  • 3
  • 20
  • 27