Visual C++ Compiler Error C3760

Message Text

please use __property keyword to declare property in managed 'class'

Circumstances

Error C3760, which the product documentation seems somehow to have overlooked, arises because __declspec (property) is used when declaring a member of a managed type. The message text directs the programmer to rewrite for consistency with the language of Microsoft’s managed extensions.

Example

For a simple example of error C3760, start with the perfectly valid

class Test
{
    int get_x (void);
    __declspec (property (get = get_x)) int x;
};

The member x of the class Test is declared with a property such that references to x as data become interpreted by the compiler as references to get_x as a called member function. Indeed, the explicit declaration of get_x on the preceding line is not required.

Now compile with /clr after changing the code so that Test is a managed type:

#using  <mscorlib.dll>

__gc class Test
{
    int get_x (void);
    __declspec (property (get = get_x)) int x;                  // C3760
};

Error C3760 directs the programmer that there is further to go with the change. The fragment ought be rewritten as something like

#using  <mscorlib.dll>

__gc class Test
{
    __property int get_x (void);
};

with definition of the data member x now implied by the language.

Coding Error

Error C3760 is detected while the compiler interprets the __declspec (property). The compiler’s ordinary practice is to interpret a specifier’s syntax in isolation and leave it to other code to check the usage. For instance, in the first example above, if what should be a data member is instead made a member function (perhaps because of an editing error),

class Test
{
    int get_x (void);
    __declspec (property (get = get_x)) int x (void);           // C2779
};

the specifier is syntactically valid as a __declspec (property) specifier and is not rejected by the code that checks the specifier for its syntax. However, even a correctly formed __declspec (property) specifier is not acceptable in the declaration of a member function. It therefore gets rejected by the code that checks the declaration of the member function.

In this sense, error C3760 also is concerned with the usage of the specifier not its syntax. To check for error C3760 is to check the circumstances of use, specifically to see if the __property keyword would have been better. To check for this while checking the specifier’s syntax is a departure from ordinary practice. As with most departures from ordinary practice, there’s no surprise to find a drop in the quality of the coding. The code that checks the syntax does not know (or care about) the circumstances of use. To hack in a check on usage risks assuming something of the circumstances, which is what the code turns out to do. Specifically, it assumes that the __declspec (property) occurs inside the definition of some class object. If this assumption happens not be satisfied already, the code falls into ill-defined behaviour and most likely faults.

Staying with the example above, it is at least plausible that a programmer might think that the following fragment is reasonable

class Test
{
    int get_x (void);
    static int x;
};

__declspec (property (get = get_x)) int Test :: x;              // C1001

especially if done in advance of any attempt to dereference x. Yet it produces an internal compiler error (C1001), as indeed does anything of the form

__declspec (property (whatever                                  // C1001

if not inside a class definition. Everything after the opening parenthesis of the property specifier is irrelevant.