从C ++ 11开始,可以编写类似
的内容#include <vector>
#include <string>
struct S
{
S(int x, const std::string& s)
: x(x)
, s(s)
{
}
int x;
std::string s;
};
// ...
std::vector<S> v;
// add new object to the vector v
// only parameters of added object's constructor are passed to the function
v.emplace_back(1, "t");
对于容器类(emplace
),是否存在C ++函数的C#类似函数,如emplace_back
或System.Collections.Generic.List
?
更新
在C#中,类似的代码可能写为list.EmplaceBack(1, "t");
而不是list.Add(new S(1, "t"));
。不记得班级名称并且每次都在这种情况下写new ClassName
会很好。
答案 0 :(得分:5)
一般来说,C#中没有类似内容,它的需求远远低于C ++。
在C#中,当你拥有List<SomeReferenceType>
时,你真正拥有的是List<ReferenceToSomeType>
,所以是一个引用列表,每个元素的大小为4或8个字节(参见How big is an object reference in .NET? )。复制引用不会导致底层对象被复制,因此它非常快(您正在复制大约4或8个字节,并且处理器已针对此操作进行了优化,因为这是本机指针的大小处理器)。因此,当您someList.Add(someReference)
时,您正在添加对List<>
的引用。
在C ++中,当你拥有std::vector<SomeType>
所拥有的是SomeType
的向量时,每个元素的大小等于sizeof(SomeType)
。在std::vector<>
中插入新元素将导致您插入的元素被复制(克隆,复制......选择您喜欢的动词)。这是一项昂贵的操作。
您使用的模式通常是创建一个对象,只是为了将其插入std::vector<>
。为了在C ++ 11中优化此操作,他们添加了两种方法:std::vector<>::emplace
方法和移动语义的std::vector<>
支持。不同之处在于移动语义必须由SomeType
类型支持(您需要一个带有noexcept
说明符的移动构造函数),而每种类型都支持emplace
(最后只是使用了贴装构造函数)。
答案 1 :(得分:3)
你可以通过扩展来改善@Boo variant 您可以使用Activator.CreateInstance创建对象实例,以使解决方案更通用。
public static class ListExtension
{
public static void Emplace<S>(this IList<S> list, params object[] parameters)
{
list.Add((S)Activator.CreateInstance(typeof(S), parameters));
}
}
注意:未检查类型和计数参数,因此如果您做错了什么,就会在运行时出错
答案 2 :(得分:0)
在c#中你可以使用扩展方法来实现你想要的东西
public static class ListExtension
{
public static void Emplace(this IList<S> list, int x, string s)
{
list.Add(new S(x, s));
}
}
然后像这样使用它
myList.Emplace(1,"t");
答案 3 :(得分:0)
您似乎遇到以下问题:
"new S"
输入的时间更长。但"add"
比"emplace"
短。通过intellisense为您添加类型(只需在键入"new "
后按 Enter ):你害怕写错了。那么你不能用List<T>
。 Intellisense将帮助您输入,编译器不允许在编译时添加错误的类型。
效果:请参阅@Xanatos answer。
list.Add(new S(1, "t"));
完全可以使用。
结论:我们emplace
中不需要C#
。