There certainly are some pitfalls when you write C++/CLI code and you know C# well but not C++/CLI. I'll avoid turning this into a list question and enumerate all of them, just the more common mistakes:
C++/CLI requires you to be specific in the language syntax about the difference between value types and reference types. You have to use the hat^ on reference type references. Like String^ foo;
. But sometimes you don't, you intentionally omit it. Like StreamReader file;
. Which enables "stack semantics", an emulation of the C++ RAII pattern. Or in other words, the compiler will automatically dispose the file variable when it goes out of scope. You know this from the C# using statement. The biggest trap is using the hat when you should not, like int^ x = 42;
. Which the compiler will accept without a complaint, but you end up with a boxed int which is extremely inefficient at runtime.
Development on the C++/CLI language and toolset stopped in 2005 and has been in maintenance mode since. It thus didn't acquire the goodies that C# got in that time frame, Linq certainly being the most significant addition. No lambda expression support, no anonymous types, no extension methods. You will not enjoy converting C# code that uses these syntax constructs.
There is only ever one reason to consider converting C# to C++/CLI, it is to take advantage of its great support for interop with unmanaged code. No need to wrangle pinvoke. A very common mistake is to compile everything to MSIL, including the native C++ code. Which works too well, the C++/CLI compiler is capable of compiling any C++ to IL as long as it is standard C++03 compliant code. But the result is inefficient, it certainly doesn't run as managed code at runtime and is jitted like normal but without the goodies from the native code generator. Which can do a better job optimizing code.
The output of the compiler is plain MSIL, the exact same kind that C# generates. Plus native code for the parts of your program where you use C++, producing a mixed-mode assembly. This gives the assembly a dependency on the bitness of the process. Or in other words, the AnyCPU target you might know from C# projects does not apply. This is something you need to be aware of in your EXE project, you must be explicit about the Platform target setting. With "x86" the common choice to ensure that your program will still work when it runs on a 64-bit operating system. If you want to run your program as a 64-bit process on a 64-bit OS then you'll need to create two builds of your C++/CLI assembly and deploy the correct one with your installer.
You have nothing to fear from a File::Exists(somefile) call, there's only one way to call that method in MSIL. The C++/CLI compiler will generate the exact same IL as the C# compiler. If you are really concerned about it then create confidence by looking at the IL with a decompiler like ildasm.exe