
Programming is difficult. With this one, I hope, does not argue. But the topic of new programming languages, or rather the search for a “silver bullet,” always finds a tumultuous 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 what is called “sad”. Well, C # / lisp / F # / Haskell / ... will not help to write an elegant application that interacts with the outside world, and that's it. All elegance is lost, you should want 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 public understanding. Now I will try.
Under the cat there are several fragments in C #, taken from the module of integration of the static code analyzer
PVS-Studio into the popular Microsoft Visual Studio environment. With these fragments, I want to show what to write, for example, in C # is not any easier than in C ++. Those who want to argue - "Wellcome in the camomments." Who wants to say that the author of the code simply does not know how to write programs - also write, discuss.
')
Simple combobox
So, the first code snippet is the handling of selecting one of three lines in the NORMAL combobox in the toolbar from the image.

Figure 1 - A simple three-line combobox
And to handle such a little one, the following code is required. Unfortunately, I had to change the formatting and remove 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 handle.
And this code is not enough. There is also a number of OnMenuMyDropDownComboGetList () function of about the same size.
Here C # was no better than any other language. No, of course, it's cool that he encapsulated OLE from me, marshaling. On C, everything would be much sadder. But just somehow everything is still not the way it is presented in books and by evangelists. Where is simplicity? I just wanted to work with the drop-down list.
Code Navigation in Visual Studio
When you click on an error message in Visual Studio, something like this will work to open the file and go 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);
}
Oh, my ... Horror. A set of magic spells. This code, being written in C #, again did not simplify the life of its developer. Who can say that 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 from the external program in the __time64_t format, and in the C # code it was necessary to use the DateTime class.
Convert __time64_t to DataTime is certainly not difficult, for this you just need to 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, was it really impossible for DateTime to do the necessary constructor? Well, why, as the interaction with the environment, so again everything has to be done in the old-fashioned way with “hands”?
Enumeration of all projects of one solution (solution)
For some task, it is necessary to sort through all the projects that are in the solution (Visual Studio solution).
Instead of 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 was needed for correct working on solution
// with unloaded projects.
continue;
}
...
First, it turns out that foreach is not available for this class. But okay, for-th use has not forgotten how to use. Secondly, if we turn to an element that is in the set, but it has a “not very correct” state, then an exception flies. As a result, the code becomes much more complicated. And the C # code is again no different from the code in another language.
findings
With this post, I wanted to show that it is far from always that C # (or other language) code is simpler than C / C + + code. And therefore, blindly believing that "you need to rewrite everything in C #" is not necessary. However, I absolutely do not think that "C # sucks," because in many places it really simplifies life.
What are the reasons for the fact that the code fragments indicated in the post look as difficult as in C ++?
- Interaction with various APIs. For example, as there was interaction with the Visual Studio API.
- Interaction with programs in other languages. For example, the type __time64_t of course came from a C ++ application.
- Interaction with the operating system. It is not always possible to dock a beautiful and correct C # code with the reality represented by Windows.
- Imperfection of data processing algorithms. If you work with strings, then you will not get anywhere from "+1" in the code, no matter what language you write.
Justifications for the code used in the examples:
- Comments are cut, the code is reduced to the minimum required in the article.
- Yes, the authors of the code do not know how to write in C #, but this does not make C # more magical.