Vala:传递通用数组会破坏值

时间:2016-09-12 12:03:05

标签: generics vala

如何将数组传递给泛型函数?以下代码编译,但输出有点损坏:

void foo<T> (T[] arr) {
    foreach (T element in arr) {
        var element2 = (int) element;
        stdout.printf (element2.to_string() + "\n");
    }
}


void main () {
    int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    foo<int> (array);
}

输出:
0
2
4
6
8
113个
0
-1521013800
0
0

我做错了什么?

1 个答案:

答案 0 :(得分:2)

您发现了编译器错误。

数组被视为一个指针数组,当foreach尝试迭代该指针数组时,就会出错。

顺便说一句:如果编译为32位,它可以工作,因为那里有sizeof(gint) == sizeof(gpointer)

编译器不应允许将值类型数组传递给泛型函数。

可以使用Gee.Collection<G>而不是数组来修复此问题:

void foo<T> (Gee.Collection<T> coll) {
    foreach (T element in coll) {
        var element2 = (int) element;
        stdout.printf (element2.to_string() + "\n");
    }
}


void main () {
    int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    foo<int> (new Gee.ArrayList<int>.wrap (array));
}

这是有效的,因为Gee.Collection<G>有自己的迭代器实现,在这种情况下似乎更安全。它也不是一个完美的解决方案,一些Gee类型的值类型参数存在问题,因为它们期望类型可以为空。

Vala中的泛型总是有点棘手,你不应该将值类型传递给泛型。

如果您使用int?(可为空的int,这是一种引用类型),它可以按预期工作:

void foo<T> (T[] coll) {
    foreach (T element in coll) {
        var element2 = (int?) element;
        stdout.printf (element2.to_string() + "\n");
    }
}

void main () {
    int?[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    foo (array);
}

Nullable类型也不完美,因为它们需要更多内存,并且它们的性能不如值类型,但这就是它的方式。

代码仍然有点问题,因为你将元素转换为int(或我的版本中的int?),但我想你知道这不是一个好主意,因为这个只是一些测试代码,对吧?