Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional parameters “must be a compile-time constant”

I have a similar problem the issue described in this SO question In my case however the optional param default values is:
1. Defined in a separate C++/CLI dll.
2. Is already defined in that lib as "public static const"
When I try to use the value as a default parameter value from C# I get "must be a compile time constant".
Is there a way to share a common const value between (C++/cli) library and (C#) app?

C++/CLI lib:

namespace MyCPlusPlusCLILib {
    public ref class CPPCLIClass {
    public:
       static const double Invalid = -1;
}

C# code:

public MyMethod(double fish = MyCPlusPlusCLILib.CPPCLIClass.Invalid) { }
// C# compiler error "Must be a compile time const"

OR

const double MyConstDouble = MyCPlusPlusCLILib.CPPCLIClass.Invalid;
// C# compiler error "Must be a compile time const"
like image 718
Ricibob Avatar asked Dec 04 '25 11:12

Ricibob


3 Answers

The const keyword in C++ declares constants that are not all that const, it can be arbitrarily cast away with a const_cast<>.

You'll need to use a C++/CLI specific keyword to declare a .NET constant, the kind whose value is stored in the metadata but doesn't also have underlying storage. Use the literal keyword:

    literal double Invalid = -1;

Which solves your problem, the C# compiler is happy with that one. Do note the iffiness of public constants. Your C# compiler will compile the value into the generated IL directly, substituting "Invalid" with the literal value. This will turn out poorly when you update your C++/CLI assembly with a bug fix that changes the literal but don't recompile the C# code. Public constants are okay for manifest constants, like Math::Pi.

like image 148
Hans Passant Avatar answered Dec 08 '25 15:12

Hans Passant


MyCPlusPlusCLILib.CPPCLIClass.Invalid is not a compile-time constant, because you could put in a different version of MyCPlusPlusCLILib, with Invalid set to a different value.

If you don't want to make the default value for the C# method an explicit -1, you could do something like this: Pick a different value for a C# default, and when you get that, substitute in the C++/CLI Invalid.

public void MyMethod(double fish = Double.NaN)
{
    if (Double.IsNaN(fish))
        fish = MyCPlusPlusCLILib.CPPCLIClass.Invalid;

    ...
}
like image 41
David Yaw Avatar answered Dec 08 '25 15:12

David Yaw


The const keyword in C++ declares constants that are not all that const, it can be arbitrarily cast away with a const_cast<>.

You'll need to use a C++/CLI specific keyword to declare a .NET constant, the kind whose value is stored in the metadata but doesn't also have underlying storage. Use the literal keyword:

    literal double Invalid = -1;

Which solves your problem, the C# compiler is happy with that one. Do note the iffiness of public constants. Your C# compiler will compile the value into the generated IL directly, substituting "Invalid" with the literal value. This will turn out poorly when you update your C++/CLI assembly with a bug fix that changes the literal but don't recompile the C# code. Public constants are okay for manifest constants, like Math::Pi.

like image 44
Hans Passant Avatar answered Dec 08 '25 15:12

Hans Passant