0

I have a C++ code which I need to rewrite to C# and looks like this:

class dppServerError: public dppBaseError
{
  public :
    dppServerError(DWORD ActionCode, const TCHAR* Desciption)
#ifdef POSTER_VER
        : dppBaseError(Desciption)
#else
        : dppBaseError(TEXT("Server text response: \"%s\""), Desciption)
#endif
        , m_AC(ActionCode), m_ErrorCode(dppERR_SERVER)
    {
    };

Problem is I am not using #defines in my C# code and instead using public const Enums. Now, how can I duplicate above code in C#? the #ifdefs part? Can't I normally initialize member variables of base class in the body of the constructor of derived class? (without : syntax). Then I could do (in C#):

   dppServerError(uint ActionCode, string Desciption)
    {
       // Initialize base class member
       if(Globals.ConfigEnum == POSTER_VER)
          dppBaseError  = Desciption; // Can I initialize this base class ivar like this? without : syntax?
       else
         dppBaseError = "Smth else" + Desciption;

        // These are just ivars from This class
        m_AC = ActionCode;
        m_ErrorCode = dppERR_SERVER;

    };

PS. Someone told me this about #defines in C#

"Be aware though: there is no guarantee that the conditional compilation symbol is the same for all projects in your solution. This will hinder reuse of your DLLs by other solutions that want different conditional compilation symbols."

And I decided to move to enums because I didn't really get what this meant. I am a bit new to .NET.

  • While you are rewriting it, you could alter the spelling of `Desciption` ... – donkopotamus Oct 08 '15 at 12:07
  • @donkopotamus: ok but that was not my question:) do you necessarily have to initialize base class variables using ":" syntax in c#? can't I do inside constructor body? –  Oct 08 '15 at 12:08
  • Relevant SO post: [Calling the base constructor in C#](http://stackoverflow.com/questions/12051/calling-the-base-constructor-in-c-sharp) – MicroVirus Oct 08 '15 at 12:10
  • I do not use C#, but presuming it follows C++, then `:` does not *initialize* base class variables, it *constructs* them ... these are subtly different things. However, if your variable types are simple (and sanely support assignment), then it should probably work just fine. – donkopotamus Oct 08 '15 at 12:14
  • @MicroVirus: Most of the solutions you linked show this approach `public MyExceptionClass(string message, Exception innerException): base(message, innerException)` - but I can't use that without #ifdefs in C#, isn't it??? –  Oct 08 '15 at 12:14
  • With C++, you'll get different versions of your dll just as well when you compile with different symbols defined, so that's not a problem specific to C#. As for syntax, C# does not support initializer lists. `:` after a constructor is only used for calling base-class constructors. Note that what's conditional in your C++ code is also a base-class constructor call - and that's something you can't switch at run-time. – Pieter Witvoet Oct 08 '15 at 12:19
  • @PieterWitvoet: What about compile time? My quesiton is if I can initialize base class member variables from the body of the constructor of the derived class? Then I can replicate the above C++ code using ifs like I showed in my question, isn't it?? –  Oct 08 '15 at 12:20
  • If the base class members aren't private, then yes, you can assign to them in the derived class' constructor. However, your C++ code doesn't assign anything conditionally, it conditionally calls a base class constructor, and that's not something you can switch at run-time - unless you rewrite the base class constructor or create a separate initialization method that can be called by both constructors. – Pieter Witvoet Oct 08 '15 at 12:24

2 Answers2

0

If dppBaseError is a field, you can initialize it as you have shown in your code.

If it's a base class constructor, you could do this:

dppServerError(uint ActionCode, string Desciption)
: base( (Globals.ConfigEnum == POSTER_VER) ? Desciption : "Smth else" + Desciption)
{
    ...
Henrik
  • 23,186
  • 6
  • 42
  • 92
  • Yeah but second case in C++ is calling two parameter constructor isn't it? I think I made a mistake in my C# code in question. –  Oct 08 '15 at 12:37
  • This is how constructor is defined on C++ side `dppBaseError(const TCHAR* ErrorMessage, ... )` –  Oct 08 '15 at 12:38
  • I think there is no big difference between #ifdef POSTER_VER and other variant. I might skip this and use just one string for initialization, what do you think? it just adds some new string in the second case as a description I guess –  Oct 08 '15 at 12:40
  • @user300224 it calls the base class constructor and passes one parameter. See https://msdn.microsoft.com/en-us/library/ty67wk28.aspx – Henrik Oct 08 '15 at 12:55
0

To get the same c++ behaviour in c#, use this:

#if POSTER_VER
     dppBaseError  = Desciption;    
#else
    dppBaseError = "Smth else" + Desciption;
#endif

or also:

dppServerError(uint ActionCode, string Desciption)
#if POSTER_VER
    :base(Desciption)
#else
    :base("Smth else" + Desciption)
#endif 

Use a #define POSTER_VER directive, or better, define the symbol in project properties -> build -> Conditional compilation symbols.

Usually a source file is included only in one project (unless you use "add as link " in visual studio to add same file to two or more projects), so the remarks "be aware" does not apply. if it does, use the same care you would use for c++ code.

In you c# code , the variable Global.ConfigEnum is evaulated at runtime, in my c# code, as in your c++, the symbol POSTER_VER is checked at complile time, resulting in different compiled binary files.

see #if, #define and ProjectProperties on MSDN

Gian Paolo
  • 4,161
  • 4
  • 16
  • 34
  • This is another comment I got about symbols: "Suppose you have a DLL with two projects, let's say a DLL and an executable that uses the DLL. In your DLL project the conditional compilation symbol MAXFILELENGTH is set to 10, but in the executable project it is set to 100. This means that your executable thinks that your DLL can handle fileLengths up to 100, while in fact it can only handle FILELENGTHS to 10. There is no way one project can ask the other for its #define" I am just not following what is the problem, since I am beginner in .NET. –  Oct 08 '15 at 13:02
  • Also what you meant here: " if it does, use the same care you would use for c++ code." ?? –  Oct 08 '15 at 13:03
  • - in c#, #define defines a symbol, not a macro: you can write #define MY_SYMBOL (and later test it with a #if, that works as a #ifdef in c++), but not #define MY_SYMBOL 10 // error in c# - In c++, if you #include "someheader.hpp" and in that file you have to be sure that the value defined form #MY_SIMBOL is the same for all the projects including that files. in c#, if the files is included in more projects and you want same compilation result, be sure to define MY_SIMBOL in all the project – Gian Paolo Oct 08 '15 at 13:36
  • but really, include the same source file in different projects is very rare in c#, and I think it's not your case . So in this case you can safely use the POSTER_VER symbol. – Gian Paolo Oct 08 '15 at 13:42