dynamic_cast to interface won't compile - c++-cli

I have some C# code like this:
string GetString(int n, CultureInfo cultureInfo)
{
T value = data[n];
IFormattable formattable = value as IFormattable;
if (formattable != null)
return formattable.ToString(null, cultureInfo)
return value.ToString();
}
I'm trying to do the same thing in a C++ generic class:
String^ GetString(int n, CultureInfo^ cultureInfo)
{
T value = data[n];
IFormattable^ formattable = dynamic_cast<IFormattable^>(value);
if (formattable != nullptr)
return formattable->ToString(nullptr, cultureInfo);
return value->ToString();
}
When I try to compile it, I get:
error C2681: 'T': invalid expression type for dynamic_cast
I'm not sure why it won't compile as I was under the understanding that dynamic_cast was similar to the as operator in C#

I saw someone mention that there are issues with generics and dynamic_cast in another post, and was able to figure it out.
I was thinking the problem was with IFormattable, but the problem is with 'value'.
It compiles fine and works if I cast the value to Object^ first:
String^ GetString(int n, CultureInfo^ cultureInfo)
{
T value = data[n];
IFormattable^ formattable = dynamic_cast<IFormattable^>((Object^)value);
if (formattable != nullptr)
return formattable->ToString(nullptr, cultureInfo);
return value->ToString();
}

Related

How do you initialize properties with custom setters that do error checking?

How can I initialize a property with a custom setter?
For example, in my setter I make sure that the value is not negative.
class Foo(length: Int) {
var length = length
set(value) {
if (value < 0) throw IllegalArgumentException("Can't be negative.")
field = value
}
}
}
However if I call it as Foo(-5) the exception doesn't call since setters aren't called when properties are initialized.
Another thing I tried was below, but then it seems wrong to set the length twice.
class Foo(length: Int) {
var length = length
set(value) {
if (value < 0) throw IllegalArgumentException("Can't be negative.")
field = value
}
}
init {
this.length = length
}
}
Finally I thought about the code below, but that seems wrong since you are checking for the wrong value in two spots.
class Foo(length: Int) {
init {
if (length < 0) throw IllegalArgumentException("Can't be negative.")
}
var length = length
set(value) {
if (value < 0) throw IllegalArgumentException("Can't be negative.")
field = value
}
}
}
Your second method is just about as clean as you can make it, although I would set the initial value to some constant like 0 rather than length. Then if you forget to assign length in an init block, you get a compiler warning that the constructor parameter is unused.
There is also a 'fourth' way (variation of your second, actually):
class Foo {
var length = 0 // You cannot even assign length here
set(value) {
if (value < 0) throw IllegalArgumentException("Can't be negative.")
field = value
}
// Having to use a warning suppression is the primary drawback of this 'fourth' way
#Suppress("ConvertSecondaryConstructorToPrimary")
constructor(length: Int) {
this.length = length
}
}
Apart from the express warning suppression annotation, this way the cleanest in my opinion, with no repetition and with minimal boilerplate.

How to Error Handle a NullReferenceException

My website went down for a few days, therefore I am trying to produce some error handling while the MVC app doesnt have access to certain resources so if something doesnt become unavailable again the WHOLE THING doesnt have to go down.
At the moment a controller is trying to access viewbag.moreNewProducts that isnt available.
public ActionResult Index(string search)
{
string[] newProductLines = this.getMoreNewProducts();
string[] newNews = this.getMoreNews();
string[] newPromotions = this.getMorePromotions();
string[] fewerProductLines = this.getLessNewProducts(newProductLines);
ViewBag.moreNewProducts = newProductLines;
ViewBag.moreNews = newNews;
ViewBag.morePromotions = newPromotions;
ViewBag.lessNewProducts = fewerProductLines;
bool disableShowMore = false;
This is where I run into an error: " foreach (string line in newProductLines)"
public string[] getLessNewProducts(string[] newProductLines)
{
int charCount = 0;
int arrayCount = 0;
string[] displayProductLines = new string[6];
bool continueWriting;
if (newProductLines == null)
{
foreach (string line in newProductLines)
{
continueWriting = false;
for (int i = 0; charCount < 250 && i < line.Length && arrayCount < 5; i++)
{
string index = newProductLines[arrayCount].Substring(i, 1);
displayProductLines[arrayCount] += index;
charCount++;
continueWriting = true;
}
if (continueWriting == true)
{
arrayCount++;
}
}
string[] LessNewProducts = new string[arrayCount];
for (int d = 0; d < arrayCount; d++)
{
LessNewProducts[d] = displayProductLines[d];
}
return LessNewProducts;
}
else
{
return null;
}
}
how do I get around an if else statement so the whole thing doesnt have to crash?
Two things.
Your if (newProductLines == null) statement has the wrong condition on it. I don't believe that you want to enter that if newProductLines is null. You can inverse this condition to get the desired result(if (newProductLines != null)).
If you run into another situation later where you need to catch an error, you can always use the try-catch block to catch exceptions that you are expecting.
try
{
//code that could cause the error here
}
catch(NullReferenceException nullRefExcep)
{
//what you want it to do if the null reference exception occurs
}
if (newProductLines == null)
should be replaced with if (newProductLines != null) so you don't have to handle the code with newProductLines as null. Basically, with this condition you will always have the NullReferenceException unless you manage your exception with a try catch block.
The real question to ask yourself is:
Why would newProductLines be null?
Presumably getMoreNewProducts() found a situation where it thought it would be appropriate to return a null value.
If this is happening because the system has an error that would make your page meaningless, then you may just want to change getMoreNewProducts() so that it throws an exception when that error state occurs. Typically it's safest and easiest to debug programs that fail as soon as they run into an unexpected situation.
If this is happening because there are no new products, then you should just return an empty collection, rather than null. All your code should work just fine after that, without the need for an if/else statement: it will return an empty array for LessNewProducts, which is probably correct.
However, let's assume that there's a situation that you're anticipating will occur from time to time, which will make it impossible for you to retrieve newProductLines at that time, but which you would like the system to handle gracefully otherwise. You could just use null to indicate that the value isn't there, but it's really hard to know which variables might be null and which never should be. It may be wiser to use an optional type to represent that getMoreNewProducts() might not return anything at all, so you can force any consuming code to recognize this possibility and figure out how to deal with it before the project will even compile:
public ActionResult Index(string search)
{
Maybe<string[]> newProductLines = this.getMoreNewProducts();
string[] newNews = this.getMoreNews();
string[] newPromotions = this.getMorePromotions();
Maybe<string[]> fewerProductLines = newProductLines.Select(this.getLessNewProducts);
Disclaimer: I am the author of the Maybe<> class referenced above.
Here are some additional improvements I'd suggest:
Don't use ViewBag. Instead, create a strongly-typed ViewModel so that you can catch errors in your code at compile-time more often:
var viewModel = new ReportModel {
newProductLines = this.getMoreNewProducts(),
newNews = this.getMoreNews(),
...
};
...
return View(viewModel);
Learn to use LINQ. It will simplify a lot of your very complicated code. For example, instead of:
string[] LessNewProducts = new string[arrayCount];
for (int d = 0; d < arrayCount; d++)
{
LessNewProducts[d] = displayProductLines[d];
}
return LessNewProducts;
... you can say:
string[] LessNewProducts = displayProductLines.Take(arrayCount).ToArray();
In fact, I think your entire getLessNewProducts() method can be replaced with this:
return newProductLines
.Where(line => line.Length > 0)
.Select(line => line.Substring(0, Math.Min(line.Length, 250)))
.Take(5);

Array allocate in function

I ve got a problem with allocating cli::array in function.
I have this kind of object:
array<double>^ tmsr2;
now I want to allocate it in function so:
void allocate(array<double>^ tmsr2)
{
tmsr2=gcnew array<double>(100);
}
Now, tmsr2 in function gets allocated well but I lose the pointer when returning to main()
The problem is clear to me, just like if I want to allocate simple array "double *a"; I need to pass pointer to function so "&a" and then everything works fine. I just don't know the syntax with managed arrays. Help much appreciated.
Peter
Since array<double> is a managed type, you can use a managed tracking reference here, instead of a plain reference.
void allocate(array<double>^% tmsr2)
{
tmsr2 = gcnew array<double>(100);
}
Here's my test app:
public ref class AsAClassField
{
public:
array<double>^ b;
AsAClassField()
{
allocate(b);
Debug::WriteLine("b = " + (b != nullptr ? "array" : "null"));
}
};
int main(array<System::String ^> ^args)
{
array<double>^ a = nullptr;
allocate(a);
Debug::WriteLine("a = " + (a != nullptr ? "array" : "null"));
AsAClassField^ foo = gcnew AsAClassField();
return 0;
}
Output:
a = array
b = array
Of course, you could always switch your allocate function to return the newly allocated array, rather than taking it as a reference. That would be more in the managed style.
You can pass the array as a reference:
void allocate(array<double>^ &tmsr2)
{
tmsr2=gcnew array<double>(100);
}

Function and delegate literals in D

Reading TDPL about function and delegate literals (5.6.1)
auto f = (int i) {};
assert(is(f == function));
I've got an assertion failure. Is this assertion correct?
I tried the following:
int z = 5;
auto f = (int i) { return i < 5; };
auto d = (int i) { return i < z; };
assert(is(typeof(f) == typeof(d)));
Assertion is valid there. Actually f is a delegate, not a function even if it doesn't need a frame pointer to access local variables. Is this a bug?
Also, I do not understand how assert(is(f == function)); should work.
I tried assert(is(f == delegate)); but it was failed also. What's wrong?
I use DMD32 D Compiler v2.053
UPDATE
auto f = (int i) {};
assert(is(typeof(f) == delegate))
Works correct, although there is no reason to be a delegate
But
auto f = function (int i) {};
assert(is(typeof(f) == void function(int))); // correct
assert(is(typeof(f) == function)); // failed!!!!!
Miracle. It seems D2 is not ready for production use yet.
"f" is a variable. The is expression compares types. This should work:
assert(is(typeof(f) == delegate));
If you want to create a function instead of a delegate, you can use the function literal syntax:
auto f = function (int i) { ... };
assert(is(typeof(f) == function)); // should be true
If the function literal syntax is not used, the literal is assumed to be delegate (Expressions, look under "Function Literals". This makes sense because D should not change the type based on the whether the body of the literal needs the stack frame (this would be super screwy). EDIT: TDPL does actually specify that the compiler will infer a function instead of a delegate if it can, regardless of the "function" keyword. This seems like a poor idea to me, so this might be something that has been dropped.
As to why the is(f == function) doesn't work, this looks like a regression.
You might find isFunctionPointer and isDelegate helpful.
Update:
See this, taken from traits.d:
template isSomeFunction(/+###BUG4217###+/T...)
if (/+###BUG4333###+/staticLength!(T) == 1)
{
enum bool isSomeFunction = isSomeFunction_bug4333!(T).isSomeFunction;
}
private template isSomeFunction_bug4333(T...)
{
/+###BUG4333###+/enum dummy__ = T.length;
static if (is(typeof(& T[0]) U : U*) && is(U == function))
// T is a function symbol.
enum bool isSomeFunction = true;
else static if (is(T[0] W) || is(typeof(T[0]) W))
// T is an expression or a type. Take the type of it and examine.
static if (is(W F : F*) && is(F == function))
enum bool isSomeFunction = true; // function pointer
else enum bool isSomeFunction = is(W == function) || is(W == delegate);
else enum bool isSomeFunction = false;
}
I think it might explain some things.
In other words:
void main()
{
static if (is(typeof(&main) T : T*)) static assert( is(T == function));
static if (is(typeof(&main) U)) static assert(!is(U == function));
}

Convert Object to the C++ built-in type

I have the following minimal code:
using namespace System;
long get_prop( Object^ v )
{
return Convert::ToInt32( v );
}
int main()
{
Object^ o1 = gcnew Int32( -1 );
Object^ o2 = gcnew UInt32( 0xFFFFFFFF );
long value1 = get_prop( o1 );
long value2 = get_prop( o2 );
return 0;
}
It gives the OverflowException exception in get_prop function. In the end I need to use the result of get_prop in pure C++ code. What is the correct way to write get_prop function so it can work without exception in both cases. Can I use some sort of templates as in C++ or there more trivial solution?
Hmya, you are trying to stuff a 32-bit pig in a 31-bit poke. This code ends up calling Convert::ToInt32(UInt32 value) which looks like this:
public static int ToInt32(uint value)
{
if (value > 0x7fffffff)
{
throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
}
return (int) value;
}
Kaboom. Not sure what kind of overflow behavior you want, but this lets the compiler do the ignoring and avoids the exception:
long get_prop( Object^ v )
{
return (long)Convert::ToInt64( v );
}