About programming difficulties, or C # will not save us?

    Picture 1
    Programming is complicated. Nobody argues with this, I hope. But here is the topic of new programming languages, or rather the search for the "silver bullet" always finds a stormy response in the minds of software developers. Especially “fashionable” is the theme of the superiority of one programming language over another. Well, for example, that C # is “cooler” than C ++. And although holy wars is not the reason why I am writing this post, nevertheless, it is called "pent up". Well, C # / lisp / F # / Haskell / will not help ... write an elegant application that interacts with the outside world, and that’s it. All elegance is lost, it is worth wanting to write something real, and not an example of "in itself."

    This post continues the thoughts of my colleague described in the post " Mmm ... Super language ... Give me C ++ please!". That article did not find understanding among the public. Now I’ll try.

    Under the cut some fragments in C # taken from the module for integrating PVS-Studio static code analyzer into the popular Microsoft Visual Studio environment. With these fragments I want to show what to write, for example, in C # it’s not at all easier than in C ++. Those who want to argue are “welcome to comments.” Who wants to say that the author of the code just doesn’t know how to write programs - write, we’ll also discuss.

    Simple combobox


    So, the first piece of code is handling the selection of one of the three lines in a NORMAL combobox on the toolbar from the image.
    Figure 1 - A simple three-line combobox
    Figure 1 - A simple combobox with three lines

    And so, to process such a wick, the following code is required. Unfortunately, I had to change the formatting and remove the comments. So I apologize for the horror.
    private void OnMenuMyDropDownCombo (object sender, EventArgs e)
    {
      if (e == EventArgs.Empty)
      {
        throw (new ArgumentException ());
      }
      OleMenuCmdEventArgs eventArgs = e as OleMenuCmdEventArgs;
      if (eventArgs! = null)
      {
        string newChoice = eventArgs.InValue as string;
        IntPtr vOut = eventArgs.OutValue;
        if (vOut! = IntPtr.Zero && newChoice! = null)
        {
          throw (new ArgumentException ());
        }
        else if (vOut! = IntPtr.Zero)
        {
          Marshal.GetNativeVariantForObject (
            this.currentDropDownComboChoice, vOut);
        }
        else if (newChoice! = null)
        {
          bool validInput = false;
          int indexInput = -1;
          for (indexInput = 0;
               indexInput <dropDownComboChoices.Length;
               indexInput ++)
          {
            if (String.Compare (
                dropDownComboChoices [indexInput], newChoice,
                true) == 0)
            {
              validInput = true;
              break;
            }
          }
          if (validInput)
          {
            this.currentDropDownComboChoice =
                dropDownComboChoices [indexInput];
            if (currentDropDownComboChoice ==
                Resources.Viva64)
              UseViva64Analysis (null, null);
            else if (currentDropDownComboChoice ==
                     Resources.GeneralAnalysis)
              UseGeneralAnalysis (null, null);
            else if (currentDropDownComboChoice ==
                     Resources.VivaMP)
              UseVivaMPAnalysis (null, null);
            else
            {
              throw (new ArgumentException ());
            }
          }
          else
          {
            throw (new ArgumentException ());
          }
        }
        else
        {
          throw (new ArgumentException ());
        }
      }
      else
      {
        throw (new ArgumentException ());
      }
    }

    And here is IntPtr.Zero and Marshal.GetNativeVariantForObject ()? Well, it’s necessary ... A simple combobox is not easy to process.

    Moreover, this code is not enough. There is also a nearby OnMenuMyDropDownComboGetList () function about the same size.

    Here C # turned out to be no better than any other language. No, of course, it's cool that he encapsulated from me OLE, marshaling. In C, everything would be much sadder. But it’s just somehow somehow all the same is not how it is presented in books and evangelists. Where is the simplicity? I just wanted to work with a drop-down list.

    Code Navigation in Visual Studio


    When you click on the error message in Visual Studio, something like this code is triggered to open the file and jump to the line with the error.
    public void OpenDocumentAndNavigateTo (string path, int line, 
      int column)
    {
    IVsUIShellOpenDocument openDoc =
                  Package.GetGlobalService (
                  typeof (IVsUIShellOpenDocument))
                  as IVsUIShellOpenDocument;
         if (openDoc == null)
           return
         IVsWindowFrame frame;
         Microsoft.VisualStudio.OLE.Interop.IServiceProvider sp;
         IVsUIHierarchy hier;
         uint itemid;
         Guid logicalView = VSConstants.LOGVIEWID_Code;
         if (ErrorHandler.Failed (
            openDoc.OpenDocumentViaProject (path, ref logicalView, 
              out sp, out hier, out itemid, out frame))
                || frame == null)
                  return
         object docData;
         frame.GetProperty ((int) __ VSFPROPID.VSFPROPID_DocData, 
           out docData);
         VsTextBuffer buffer = docData as VsTextBuffer;
         if (buffer == null)
         {
              IVsTextBufferProvider bufferProvider = 
                  docData as IVsTextBufferProvider;
              if (bufferProvider! = null)
              {
                IVsTextLines lines;
                ErrorHandler.ThrowOnFailure (
                  bufferProvider.GetTextBuffer (out lines));
                buffer = lines as VsTextBuffer;
                if (buffer == null)
                  return
              }
         }
      IVsTextManager mgr = 
        Package.GetGlobalService (typeof (VsTextManagerClass))
        as IVsTextManager;
      if (mgr == null)
        return
      mgr.NavigateToLineAndColumn (
         buffer, ref logicalView, line, column, line, column);
    }

    Yo-my ... Horror. Set of magic spells. This code, once written in C #, again made life easier for its developer. Who says it will look better in XYZ? The language here is “perpendicular” to the problem being solved and has practically no effect.

    Work with date


    Well, work with dates in C # should be exactly on top! After all, there are so many different convenient formats made. I thought, until the time came in the __time64_t format from an external program, and in the C # code it was necessary to use the DateTime class.

    Converting __time64_t to DataTime is certainly not difficult, just write a function like this:
    public static DateTime Time_T2DateTime (long time_t)
    {
      // 116444736000000000 - this is 1600
      long win32FileTime = 10000000 * time_t + 116444736000000000;
      return DateTime.FromFileTime (win32FileTime);
    }

    And here C # turned out to be no better ... Perhaps of course I did not find the conversion function. Well, really it was impossible to make the necessary constructor at DateTime? Well, why, like interacting with the environment, so again, in the old fashion, you have to do the “pens"?

    Enumeration of all projects of one solution (solution)


    For some tasks, it is necessary to sort through all the projects that are in the solution (Visual Studio solution).

    Instead of a simple and elegant foreach, the code looks like this:
    Solution2 solution = PVSStudio.DTE.Solution as Solution2;
    SolutionBuild2 solutionBuild = 
        (SolutionBuild2) solution.SolutionBuild;
    SolutionContexts projectContexts = 
        solutionBuild.ActiveConfiguration.SolutionContexts;
    int prjCount = projectContexts.Count;
    for (int i = 1; i <= prjCount; i ++)
    {
        SolutionContext projectContext = null;
        try
        {
            projectContext = projectContexts.Item (i);
        }
        catch (Exception)
        {
            // try / catch block is a workaround. 
            // It's needed for correct working on solution 
            // with unloaded projects.
            continue;
        }
    ...

    Firstly, it turns out that foreach is not available for this class. But all right, for-ths have not yet forgotten how to use. Secondly, if we turn to the element that is in the set, but it has a “not very correct” state, then an exception flies. As a result, the code is noticeably more complicated. And the code in C # again is no different from the code in another language.

    conclusions


    With this post I wanted to show that the code in C # (or another language) is not always simpler than the code in C / C ++. And therefore, blindly believing that "you need to rewrite everything in C #" is not necessary. Nevertheless, I absolutely do not think that “C # sucks”, because in many places it really simplifies life.

    What are the reasons that the code snippets mentioned in the post look just as complicated as they do in C ++?
    1. Interaction with various APIs. For example, as there was interaction with the Visual Studio API.
    2. Interaction with programs in other languages. For example, the type __time64_t, of course, came from a C ++ application.
    3. Interaction with the operating system. It is far from always possible to dock a beautiful and correct C # -code with reality in the face of Windows.
    4. Imperfection of data processing algorithms. If you work with strings, then from "+1" in the code you will not go anywhere, no matter what language you write.

    Justification for the code used in the examples:
    1. Comments are cut out, the code is reduced to the minimum necessary in the article.
    2. Yes, the authors of the code do not know how to write in C #, but from this C # does not become more magical.


    Also popular now: