我正在包装本机C类,它具有以下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Native
{
public:
class Local
{
std::string m_Str;
int m_Int;
};
typedef std::vector<Local> LocalVec;
typedef LocalVec::iterator LocalIter;
LocalIter BeginLocals();
LocalIter EndLocals();
private:
LocalVec m_Locals;
}; |
1)表示这种类型的接口的" .NET方式"是什么?一个方法返回一个数组<>? array <>泛型是否具有迭代器,以便可以实现BeginLocals()和EndLocals()?
2)是否应在.NET包装器中将Local声明为值结构?
我真的很想用.NET风格表示包装好的类,但是对于托管世界来说我是一个新手-这种类型的信息使Google感到沮丧...
迭代器不能完全翻译为" .net方式",但是它们被IEnumerable < T >和IEnumerator < T >大致替代。
而不是
1 2 3 4 5 6 7 8 9 10 11 12 13
| vector<int> a_vector;
vector<int>::iterator a_iterator;
for(int i= 0; i < 100; i++)
{
a_vector.push_back(i);
}
int total = 0;
a_iterator = a_vector.begin();
while( a_iterator != a_vector.end() ) {
total += *a_iterator;
a_iterator++;
} |
您会看到(在C#中)
1 2 3 4 5 6 7 8 9 10
| List<int> a_list = new List<int>();
for(int i=0; i < 100; i++)
{
a_list.Add(i);
}
int total = 0;
foreach( int item in a_list)
{
total += item;
} |
或更明确地(不将IEnumerator隐藏在foreach语法糖的后面):
1 2 3 4 5 6 7 8 9 10 11
| List<int> a_list = new List<int>();
for (int i = 0; i < 100; i++)
{
a_list.Add(i);
}
int total = 0;
IEnumerator<int> a_enumerator = a_list.GetEnumerator();
while (a_enumerator.MoveNext())
{
total += a_enumerator.Current;
} |
如您所见,foreach只是为您隐藏了.net枚举器。
所以,"。net方式"实际上就是让人们自己创建List 项目。如果确实要控制迭代或使集合更具自定义性,请让您的集合也实现IEnumerable < T >和/或ICollection < T >接口。
几乎直接翻译成c#就是您的假设:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Native
{
public class Local
{
public string m_str;
public int m_int;
}
private List<Local> m_Locals = new List<Local>();
public List<Local> Locals
{
get{ return m_Locals;}
}
} |
那么用户将能够
1 2 3 4
| foreach( Local item in someNative.Locals)
{
...
} |
@Phillip-谢谢,您的回答确实使我朝着正确的方向开始。
看到代码,并在Nish的C / CLI in Action中做更多的阅读之后,我认为使用索引属性将const跟踪句柄返回到托管堆上的Local实例可能是最好的方法。我最终实现了类似于以下内容的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public ref class Managed
{
public:
ref class Local
{
String^ m_Str;
int m_Int;
};
property const Local^ Locals[int]
{
const Local^ get(int Index)
{
// error checking here...
return m_Locals[Index];
}
};
private:
List<Local^> m_Locals;
}; |