What is the C++CLI equivalent of vb's Nothing? - c++-cli

I'm in this kind of a place
generic <typename ItemType> where ItemType : ItemBase
public ref class Container {
ItemType GetItem(int i) {
...
if (someSpecialCondition) return ???
...
}
};
I want to return the equivalent of vb's "Nothing" but can't figure out the syntax for it. It doesn't like null or nullptr, I know that much.

It is pretty unintuitive for generics, note that it can't be nullptr if the type parameter is a value class. It also does not match the language spec, which promises that nullptr is valid when the type is constrained to ref class.
The default value for type T is T(). So it is:
ItemType GetItem(int i) {
...
if (someSpecialCondition) return ItemType();
...
}
Which produces nullptr if ItemType is a reference type and the default value (all members zero-initialized) when ItemType is a value type. Same thing that Nothing does in VB.NET

Related

Infer property type if not null

I have a function like the following:
fun getCommonItemsFrom(element: Element): List<ElementItem>? =
if (element.parent is CommonElementWrapper) element.items
else null
So let's assume that Element has a property called parent, which is of type ElementWrapper? (an interface). And this property may or may not be a concrete instance of CommonElementWrapper.
This function returns the items (that is non-nullable List<ElementItem>) of an Element, as long as the parent property is an instance of CommonElementWrapper, otherwise null will be returned.
So I can use it like this:
if (getCommonItemsFrom(element) == null) {
return
}
// At this point I can infer that `element.parent` is a `CommonElementWrapper`.
// Since the above condition was not `null`.
if (element.parent.isSomeCommonElementWrapperThing()) {
// Error: I can't use it this way without first re-checking the parent type.
// ...
}
But currently I need to double check:
if (element.parent is CommonElementWrapper &&
element.parent.isSomeCommonElementWrapperThing()) {
// ...
}
I was wondering if Kotlin has some way of after a certain function is executed it allows to infer some things from there. Something like:
#InferIfReturnIsNotNull (element.parent is CommonElementWrapper)
fun getCommonItemsFrom(element: Element): List<ElementItem>? = ...

Overriding parameter types?

I would like to override the parameter type of a method in its subclasses, I thought generics could be used for this but that does not seem to work (at least not the way I am doing it).
abstract class A {
bool someMethod<T>(T x);
}
Then override it like so:
class B extends A {
bool someMethod<bool>(bool x) {
// error: isn't a valid override
}
}
I have had to default to using type dynamic x for the parameter type, but that forfeits runtime safety checks and means a lot of type checking whenever the method is implemented.
Is this type of extension possible?
It's possible, but not the way you do it.
What you declare is a generic method, where each invocation gets to pass the type argument to the function.
What you probably want is:
abstract class A<T> {
bool someMethod(T x);
}
class B extends A<bool> {
bool someMethod(bool x) {
return true;
}
}
That makes the type a parameter of the subclass, not the method, so each subclass can define its own type.
(Here you get into problems with Dart's covariant generics, because you can write:
A<Object> a = B();
a.someMethod("a"); // run-time error.
Your type variable occurs only in places where a value of that type is needed, not where one is provided, so casting to the superclass A<Object> make the method more permissive than it can support. The compiler inserts a run-time type check on the argument, which is what the example code here hits.)

Mixed C++/CLI overloading

Is this a proper restriction on overloading behavior. I can't figure out how to replicate a similar issue in pure C++ to compare behavior.
C++/CLI code:
class A {};
List<int>^ g(A &) {
return gcnew List<int>();
}
template<typename T>
List<T>^ g(T &) {
return gcnew List<T>();
}
void f() {
g(A()); // compiler error C3235
}
Generates:
error C3225: generic type argument for 'T' cannot be 'A', it must be a
value type or a handle to a reference type
The problem appears to be from the return values. It's requiring that the templated g() has a valid definition even though the non-templated g() overload should (shouldn't it?) be selected.

Does PetaPoco handle enums?

I'm experimenting with PetaPoco to convert a table into POCOs.
In my table, I've got a column named TheEnum. The values in this column are strings that represent the following enum:
public enum MyEnum
{
Fred,
Wilma
}
PetaPoco chokes when it tries to convert the string "Fred" into a MyEnum value.
It does this in the GetConverter method, in the line:
Convert.ChangeType( src, dstType, null );
Here, src is "Fred" (a string), and dstType is typeof(MyEnum).
The exception is an InvalidCastException, saying Invalid cast from 'System.String' to 'MyEnum'
Am I missing something? Is there something I need to register first?
I've got around the problem by adding the following into the GetConverter method:
if (dstType.IsEnum && srcType == typeof(string))
{
converter = delegate( object src )
{
return Enum.Parse( dstType, (string)src ) ;
} ;
}
Obviously, I don't want to run this delegate on every row as it'll slow things down tremendously. I could register this enum and its values into a dictionary to speed things up, but it seems to me that something like this would likely already be in the product.
So, my question is, do I need to do anything special to register my enums with PetaPoco?
Update 23rd February 2012
I submitted a patch a while ago but it hasn't been pulled in yet. If you want to use it, look at the patch and merge into your own code, or get just the code from here.
I'm using 4.0.3 and PetaPoco automatically converts enums to integers and back. However, I wanted to convert my enums to strings and back. Taking advantage of Steve Dunn's EnumMapper and PetaPoco's IMapper, I came up with this. Thanks guys.
Note that it does not handle Nullable<TEnum> or null values in the DB. To use it, set PetaPoco.Database.Mapper = new MyMapper();
class MyMapper : PetaPoco.IMapper
{
static EnumMapper enumMapper = new EnumMapper();
public void GetTableInfo(Type t, PetaPoco.TableInfo ti)
{
// pass-through implementation
}
public bool MapPropertyToColumn(System.Reflection.PropertyInfo pi, ref string columnName, ref bool resultColumn)
{
// pass-through implementation
return true;
}
public Func<object, object> GetFromDbConverter(System.Reflection.PropertyInfo pi, Type SourceType)
{
if (pi.PropertyType.IsEnum)
{
return dbObj =>
{
string dbString = dbObj.ToString();
return enumMapper.EnumFromString(pi.PropertyType, dbString);
};
}
return null;
}
public Func<object, object> GetToDbConverter(Type SourceType)
{
if (SourceType.IsEnum)
{
return enumVal =>
{
string enumString = enumMapper.StringFromEnum(enumVal);
return enumString;
};
}
return null;
}
}
You're right, handling enums is not built into PetaPoco and usually I just suggest doing exactly what you've done.
Note that this won't slow things down for requests that don't use the enum type. PetaPoco generates code to map responses to pocos so the delegate will only be called when really needed. In other words, the GetConverter will only be called the first time a particular poco type is used, and the delegate will only be called when an enum needs conversion. Not sure on the speed of Enum.Parse, but yes you could cache in a dictionary if it's too slow.
If you are using PetaPoco's T4 generation and you want enums in your generated type, you can use the PropertyType override in Database.tt:
tables["App"]["Type"].PropertyType = "Full.Namespace.To.AppType";
I you want to store the value of the enum instead of the index number (1,2,4 for example) you can locate the update function in PetaPoco class because the code is "managed" etc, when you add it as nuget package it will store the .cs file to your project. If we would have the enum variable Color = {red, yellow, blue}
Instead of:
// Store the parameter in the command
AddParam(cmd, pc.GetValue(poco), pc.PropertyInfo);
change to:
//enum?
if (i.Value.PropertyInfo.PropertyType.IsEnum)
{
AddParam(cmd, i.Value.GetValue(poco).ToString(), i.Value.PropertyInfo);
}
else
{
// Store the parameter in the command
AddParam(cmd, i.Value.GetValue(poco), i.Value.PropertyInfo);
}
It would store "yellow" instead of 2

How to use Nullable types in c++/cli?

I have the following code, which I thought would work:
property Nullable<double> Angle {
Nullable<double> get() {
return nullptr;
}
}
It doesn't. How can I do it? Does c++/CLI even support nullable types?
OK, found it, after a lot of hassle:
to return null, just do
return Nullable<double>();
to return non-null:
return Nullable<double>(12321);
It is important to declare the return value as Nullable<double> and not Nullable<double>^, as if you do it, when using other languages as C# and vb.net, you'll see the type as ValueType instead of double?.