In Managed C++, what is the proper way to define a static singleton instance in a class? - c++-cli

Jumping to Visual Studio 2015 from Visual Studio 2013, I've noticed some differences in how static self-instances in managed C++ classes are accepted by the compiler. Consider these two examples:
Method 1:
public ref class CResourceManager
{
public:
static property CResourceManager^ Instance
{
CResourceManager^ get() { return %m_Instance; }
}
private:
static CResourceManager m_Instance;
};
Method 2:
public ref class CResourceManager
{
public:
static property CResourceManager^ Instance
{
CResourceManager^ get() { return m_Instance; }
}
private:
static CResourceManager^ m_Instance = gcnew CResourceManager;
};
Method 1 used to work on 2013, but it's failing to compile on 2015. I unfortunately do not have the exact compiler error handy, but it was one of those "Missing semicolon before variable name" errors, basically saying it couldn't find the type CResourceManager (pointing to the static variable declaration).
So on to my questions:
Is method 1 supposed to work or be valid in managed C++?
Why would the second method work in 2015, but not the first (i.e. what are the differences)?
Which method is the proper way to accomplish the end goal?

Method 2 is the proper way to do it. The code you have listed is the equivalent of the C# idiom.
Method 1 is a bit unusual.
The lack of a ^ on a declaration would normally mean that the variable is not allocated on the managed heap. However, since it's a static class member, I'm not sure where it actually gets created.
% is normally used for declaring tracking references, the equivalent of passing a variable by ref or out in C#. To be honest, I didn't think that applying % to a variable without either ^ or % and taking the result as a ^ was even valid. (Though considering the 2015 compiler rejects it, it may not be.)
Even if Method 1 is valid, I'd still go with Method 2: The storage location of m_Instance and how it's returned are both plain, common, and easy to understand. This beats having to think about how the code works any day.

Related

Getter setter in C# VS2017

I've been starting to use VS2017 Community. This bugs me:
Below is normal getter setter from previous VS:
public string Name
{
get{ return _name;}
set{ _name = value;}
}
This is the new getter setter:
public string Name { get => _name; set => _name = value; }
Anyone can explain to me why the syntax is changed?
I wouldn't say they changed it, I would say they gave us some new syntax options. You can still use the "old" way of declaring getters and setters, but there is now also a more functional programming style of doing it as well. In C#6 Microsoft already introduced using expressions for getter only properties doing:
public int SomeProp => someMethod();
C#7 enhanced this support allowing it to be used for getters AND setters. One nice feature of this is with the new "throw expressions" feature which allows us to make some concise syntax. For example, before you had to do.
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (value == null)
throw new ArgumentNullException(nameof(Name));
_name = value;
}
}
We can now simplify this to:
private string _name;
public string Name {
get => _name;
set => _name = value ?? throw new ArgumentNullException(nameof(Name));
}
Granted, you could do the throw expression even without making the setter a lambda, but as you can see, for simple things, it makes the syntax very concise.
As with anything, use the syntax that makes the most sense to you and is most readable for the people who will be coding your application. Microsoft has been making a push to add more and more functional programming style features to C# and this is just another example of that. If you find it ugly/confusing/not needed, you can absolutely accomplish everything you need with the existing method. As another example, why do we have while and do while loops? I can honestly say I've used a do while loop maybe 5 times in my career. A while loop can do everything a do while can just with different syntax. However, there are sometimes where you realize that using a do while will make your code more readable, so why not use it if it makes things easier to follow?
The syntax hasn't changed: it has been improved. C# has been always backwards-compatible with syntax and grammar from previous versions.
Why property getters/setters can be implemented with lambda syntax (expression-bodied accessors)? Probably there's no scientific reason to do so, but there's a consensus about introducing useful functional programming constructs in C# as it turns the language into a more productive tool.
Just foillow up C#'s evolution since C# 2.0:
From delegates provided as regular methods to anonymous delegates.
LINQ, lambda-style delegates/expression trees.
Expression-bodied methods.
...and expression-bodied accessors! And probably future C# versions will introduce even more functional programming-style syntax and grammar.
You'll notice they removed the 'return' syntax, this was done (from what I've read) to make it more clear that they aren't functions (and when reflected can't be treated as functions and can't be made into delegates) but rather this kind of 'pseudo-function' (if you get what I'm trying to well get at).
So basically its to make it more clear that the getter is linking this this variable and the repeating for the setter. It also is because in newer versions you can do something like
public int MyInt => x ? y:z;
Which represents
public int MyInt
{
get
{
return x ? y:z;
}
}
Also both syntax should work, its just a new syntax that they added to bring it in line with the above example.
I know I am adding this details after a year, but just understood that my VS 2017 generated new syntax on my web user control, and that does not reflect on the aspx file when I wanted to set a value for it.
like
private bool _ShowBankDetailPanel = false; //To Show Bank details section in registration
public bool ShowBankDetailPanel { get => _ShowBankDetailPanel; set => _ShowBankDetailPanel = value; }
and on ASPX side you will NOT have property like
it is only recognize
old style getter setter....(I experience this,,, but I am be wrong)

Cannot cast pointer field while can cast same pointer defined within method in managed classes

I have unmanaged object of WtfClass.
class WtfClass { };
And I also have managed class which uses pointer to this object.
ref class MyClass //works fine if you remove "ref"
{
public:
void MyMethod();
void WtfMethod(void * pVoid);
WtfClass *pWtfStruct;
};
void MyClass::MyMethod()
{
/*WtfClass* pWtfStruct; //if you uncomment this it will compile even with ref*/
WtfMethod((int*)(&pWtfStruct)); //(!!!invalid type conversion here)
}
void MyClass::WtfMethod(void *pVoid)
{}
I can't cast WtfClass* pointer from field, but can easily cast the same pointer defined within MyMethod(). If make MyClass unmanaged it works in any case.
It's better to look at screenshots:
https://ibin.co/2iOcN1ooaC7A.png [using ref-bad.png]
https://ibin.co/2iOcYtP84H0e.png [using ref-good.png]
ibin.co/2iOcjCCc2gQe.png [without ref.png] (sorry not enough reputation to paste more than 2 links)
Of course I can have workaround like this, but I'd like to understand why this happening:
void MyClass::MyMethod()
{
WtfClass* pWorkAround = pWtfStruct; //not required in this case
WtfMethod((void*)(&pWorkAround));
}
OK, so to summarize, without the duplicate field & local variable names:
ref class MyClass
{
WtfClass* fieldWtfPtr;
void foo()
{
WtfClass* localvarWtfPtr;
WtfMethod((int*)(&fieldWtfPtr)); // Error
WtfMethod((int*)(&localvarWtfPtr)); // Works
}
};
Side question: &fieldWtfPtr is of type WtfClass**, a double pointer. Did you mean to cast that to a int**, also a double pointer? Or perhaps did you want to take fieldWtfPtr as a WtfClass* single pointer and cast that to a int* single pointer?
Here's why you're getting the error: MyClass is a managed object. The garbage compiler is allowed to move it around at any point, without telling you. So, it's location in memory can change at any point. So when you try to take the address of a class field, it's not valid because the address of that field can change at any point!
Why the other things make it work:
Local variables are stored on the stack, and the stack doesn't get moved around by the garbage collector, so it is valid to take the address of a local variable.
If you remove the ref, then MyClass is no longer a managed object, so the garbage collector won't move it around, so now the addresses of its fields won't change willy-nilly.
For this case, the easiest fix would be to make use of a local temporary variable.
void foo()
{
WtfClass* localCopyWtfPtr = this->fieldWtfPtr;
WtfMethod((int*)(&localCopyWtfPtr)); // Works
// If WtfMethod changed the data, write it back.
this->fieldWtfPtr = localCopyWtfPtr;
}
When I tried to recreate this, the compiler generated the following error:
error C2440: 'type cast' : cannot convert from 'cli::interior_ptr<CWtfClass*>' to 'LPVOID *'
I think what is going on here is some magic that allows managed classes to have unmanaged members. The MSDN documentation for cli::interior_ptr describes what's going on - basically this is used to allow for the managed object to change its memory address in the managed heap, which would cause problems when native pointers come in to play.
The reason that assigning the member to a variable first works is most likely because it has an implicit conversion to the template parameter, but since it is a managed type the compiler won't allow you to get the address of the variable (since the garbage collector can move it around in memory as needed).
The workaround in your question is probably the best way to fix this compiler error.
David answered why this happens and suggested a workaround for your case.
I'll just post a different solution here: You can pin your managed object to tell the GC not to move it around. The most lightweight way to do that is through pin_ptr (the GC won't even know you pinned something unless it stumbles upon your code in the middle of a collection). As long as it stays in scope, the managed object will be pinned and won't move. It's best if you avoid pinning for too long, but this lets you get a pointer to a chunk of managed memory which is guaranteed not to move - it's helpful when you want to avoid copying things around.
Here's how to do it:
pin_ptr<WtfClass*> pin(&pWtfStruct);
WtfMethod(pin);
pin acts just like a WtfClass**.
Regarding side question of David Yaw.
I faced with this problem while used some WINAPI functions.
IAudioEndpointVolume* pWtfVolume = NULL;
pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pWtfVolume);
pWtfVolume->SetMute(BST_CHECKED, pGuidMyContext);
And it's working only if I pass &pWtfVolume. Ironically you can pass argument without "&", just pFieldVolume and compiler will say OKAY, but interface IAudioEndpointVolume will not work.
Look at this:
ref class MyClass
{
WtfClass* fieldWtfPtr;
void foo()
{
WtfClass* localvarWtfPtr;
WtfMethod((int*)(&fieldWtfPtr)); // Error
WtfMethod((int*)(&localvarWtfPtr)); // Works
WtfMethod((int*)(fieldWtfPtr)); // Compiles!!!
}
};

Cannot assign to an element of an initonly array?

It seems commonly thought that C++/CLI's initonly is the equivalent of C#'s readonly keyword. However, the following:
ref class C {
C();
void Method();
initonly array<int>^ m_array;
};
C::C() {
m_array = gcnew array<int>(10);
}
void C::Method() {
m_array[0] = 5; // Fails with C3893
}
The full error is "'C::m_array': l-value use of initonly data member is only allowed in an instance constructor of class 'C'".
The error message seems strange as I'm not using m_array as the target of an assignment, this is the equivalent of writing
m_array->SetValue(5, 0);
which incidentally compiles fine and does the same thing.
Is this bugged in C++/CLI or by design? By the way, is there any performance penalty to using Array::SetValue vs using the accessor?
A similar (but not identical) case was reported and apparently filed as a bug for VS2008: http://bytes.com/topic/net/answers/847520-initonly-but-not-bug-vc-2008-clr . I'm using Visual Studio 2012.
Yes, that's a bug. It's enforcing something which is not implied by the .NET type system, and the enforcement is ineffective.
But don't use Array::SetValue, which involves boxing and is not type safe. You can just do:
auto array = m_array; // another handle to same array
array[0] = 5;

c++/cli reference to property

Well, I haven't yet found something that says this is impossible, though I'm starting to think it might be. Can you make this work?
using namespace System;
template <typename T>
void unset(Nullable<T>& var) { var = Nullable<T>(); }
void unset(String^% var) { var=nullptr; }
//this is really a C# class in my situation, so I can't change its types
public ref class Foo
{
public:
property Nullable<Decimal> Dec;
property Nullable<int> Num;
property String^ Str;
};
int main()
{
Foo^ foo = gcnew Foo;
foo->Dec = Decimal(1.2);
foo->Num = 3;
foo->Str = "hi";
unset(foo->Dec);
unset(foo->Num);
unset(foo->Str);
Console::WriteLine(foo->Dec);
Console::WriteLine(foo->Num);
Console::WriteLine(foo->Str);
}
Update: unset is called from a code-generating macro which is called on about 50 params. I'd prefer not to have to go make varieties of the macro for each type.
It isn't possible. Setting a property requires calling the property setter function. There is no way to guess for the called method that it needs to call a function vs can assign the passed variable pointer. If you really want to do this then pass a delegate.
There is actually one .NET language that supports it, VB.NET generates code like this:
T temp = obj->prop;
func(temp)
obj->prop = temp;
There is however a dreadful aliasing problem with that, quite undebuggable. This goes belly up in the (rare) case where func() also uses the property. This is otherwise the way you'd work around the limitation, explicitly in your own code.
Beware that your code is wrong, possibly intentional, you are passing a C++ & reference, not a managed % interior pointer. The compiler is going to bitch about that, you can't create references or pointers to managed objects. They move. Unless the reference is to a variable on the stack. It doesn't otherwise change the answer.
For those who may end up here wondering how I got on with this, I ended up being lucky that the class I was working with was an LLBLGen Entity, so I was able to replace
unset(re->var);
with
{ SD::LLBLGen::Pro::ORMSupportClasses::IEntityField2^ f = re->Fields[#var]; \
if (f->IsNullable) \
f->CurrentValue = nullptr; }

C++ Ref class not a member of System::IDisposable; trouble implementing IDisposable

I want to make a global vector of my own object class called "Person". However, the compiler says that
error C2039: '{dtor}' : is not a member of 'System::IDisposable'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::IDisposable'
So I looked up how to implement IDisposable (which I now know is used primarily for unmanaged resources) but still can't seem to implement it with the following:
ref class Globals : System::IDisposable
{
public:
static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
void Dispose()
{
delete person_data;
}
};
The 2 errors I get are:
error C2605: 'Dispose' : this method is reserved within a managed class
1> did you intend to define a destructor?
error C3766: 'Globals' must provide an implementation for the interface method 'void System::IDisposable::Dispose(void)'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::IDisposable::Dispose'
You don't have to explicitly derive from IDisposable. Following the MSDN doco, use the following pattern:
ref class Globals
{
public:
static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
!Globals() // finalizer
{
delete person_data;
{
protected:
~Globals() // destructor calls finalizer
{
this->!Globals();
}
};
Use a destructor. In C++/CLI ~ClassName() is Dispose() and !ClassName() is equivalent to C#'s ~ClassName(). In your case:
ref class Globals : System::IDisposable
{
public:
static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
void ~Globals()
{
delete person_data;
}
};
use a finalizer as shown at http://www.codeproject.com/KB/mcpp/cppclidtors.aspx
You don't need to implement Dispose() yourself, either directly or via a destructor. The implicitly-generated destructor already destroys all member objects. The IDisposable interface will be added automatically, don't mention it explicitly.
Next, you need to make up your mind whether person_data is a handle (which has to be set to an instance created with gcnew) or member object semantics (like stack semantics, the constructor is automatically called by the constructor of the parent object, the destructor called automatically when the lifetime of the parent object ends, and you use "." instead of "->" to access members).
Also, are you sure you want one copy of person_data shared between all instances of "Globals", but destroyed by the first instance to be disposed, leaving any other instances holding an invalid reference (reference to disposed object)? It looks like you're trying to use a Singleton anti-pattern here, is that correct?
From C++/CLI in Action The C++/CLI Dispose pattern has these rules (paraphrased):
If a class has a finalizer or a
destructor the compiler generates
Dispose(bool) that will call either
the finalizer or destructor based on
the bool value.
If it has just a d'tor (~type) then the compiler calls
Dispose(true) so the d'tor is called.
If it has just a finalizer (!type)
then the compiler calls
Dispose(false) so the finalizer is
called
Also for the second rule: The compiler will implement the IDisposable interface for you (by generating Dispose()). It then uses SuppressFinalize to make sure the finalizer isn't called.
I did this to your code and the only way I could get it to compile was to make person_data a instance member. The error i got when it was static was error C2039: '{dtor}' : is not a member of 'System::IDisposable' which doesn't make much sense.
Also, do you even need to delete the person_data vector since is a managed object? Maybe you do but I haven't used the cliext enough to say.
Edit Perhaps the first paragraph of this article has the answer (emphasis mine):
When you declare a member variable as
static and when the application
starts, the compiler creates a copy of
that member. This member would be
maintained by the compiler while the
program is running. If you declare an
instance of a class, like the above
vehicle variable, the static member is
not part of the object: the compiler
creates and maintains the static
member, whether you use it or not,
whether you declare a class variable
or not.