Поделиться через


Dump Environment Folder Paths

This is just a quick snippet to dump the value of Environment.GetFolderPath for all special folders on a machine (so I don’t have to write it again next time):

 public static string DumpEnvironmentPaths()
{
    var paths = Enum.GetValues(typeof(Environment.SpecialFolder))
        .Cast<Environment.SpecialFolder>()
        .Select(folder => folder + " = " + Environment.GetFolderPath(folder))
        .Aggregate((line1, line2) => line1 + Environment.NewLine + line2);
    return paths;
}

Also, I’m using the opportunity to give Rick Strahl’s CodePaste.NET service a spin: https://codepaste.net/uo7zx8.

“CodePaste.NET is a public site for pasting snippets of code and linking to them from social network sites.”

As for the code itself (envisioning potential rotten tomatoes flying my way), several things are probably worth mentioning:

  1. First, the code is written in a more functional style, being more explicit about its intent. I think it shows more clearly the input data and the output data, how the data flows and what operations are performed on the input data.
  2. Second, I have a temporary local variable instead of returning the expression immediately. This is for easier debugging, because if you don’t have a temporary variable, you won’t be able to view the return value of the method easily in the debugger. With a temporary local, you can put a breakpoint on the return statement and inspect the results of the query. Someday the tools will be improved and will allow to inspect the return value of methods.
  3. I’m using Aggregate instead of string.Join or StringBuilder because it composes better. On large data volumes, this approach is horrible because it will allocate a ridiculous amount of unnecessary intermediate strings. StringBuilder and string.Join are much more frugal in this respect, so don’t use Aggregate with strings this way. However, in this particular example, the number of strings is O(1), so I just picked the approach that composes better. Unfortunately, string.Join doesn’t compose well at all and was never intended to be used in a fluent API.

Comments

  • Anonymous
    September 27, 2009
    Regarding 2, I've been watching return values in the "autos debug window" for a while now, in native code. I'd assume it would work in c#? (I still write the return with a local var in my own code, but I deal with a lot of code that does not follow that pattern).

  • Anonymous
    September 27, 2009
    I suppose you could have used another overload of Aggregate, that takes a StringBuilder as a seed? That way it still composes well, because StringBuilder.Append returns itself. Well...there's side-effect in it, but the code still shows its intents, right?

  • Anonymous
    September 29, 2009
    The comment has been removed

  • Anonymous
    September 29, 2009
    ravenex: yes, that would be possible. But I'm starting to think that Alois is right, maybe everything looks like a nail to me now that I have a hammer in my hand... Alois, I'll be frank, I don't even know what to answer. Those are two different styles of coding. I used to write code like in your example - that's one approach and there's nothing wrong with that. Now as I'm exploring new ways, I tend to write code in "my style" (see my example). I liked the second one better, but maybe I'm wrong. I'll have to think more about and possibly ask more people. Anyway thanks for the interesting feedback! Do let me know if you have more thoughts on the subject. Thanks, Kirill

  • Anonymous
    September 29, 2009
    bahbar: I checked and the autos window doesn't display anything for C# in this case... I don't know, maybe C++ has some sort of special support for viewing method return values in the debugger??! No idea.

  • Anonymous
    September 30, 2009
    The comment has been removed

  • Anonymous
    October 06, 2009
    I would have done it a bit different - see http://codepaste.net/fzpmah - I prefer returning IEnumerable<string> and then Join-ing the strings (I have an extension method taking an IEnumerable<string> and a separator). As for Alois' question... well, since discovering functional programming I prefer to separate ceremony from the actual algorithm, and I consider foreach to be ceremony. It's not something I insist the other programmers on my team to do, but I personally hunt all for's and foreach's in my code and try to replace them by their functional equivalent. I guess it just "feels" more natural.