是否有C ++ 11 emplace / emplace_back函数的C#模拟?

时间:2016-03-14 11:04:54

标签: c# collections emplace

从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_backSystem.Collections.Generic.List

更新 在C#中,类似的代码可能写为list.EmplaceBack(1, "t");而不是list.Add(new S(1, "t"));。不记得班级名称并且每次都在这种情况下写new ClassName会很好。

4 个答案:

答案 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)

您似乎遇到以下问题:

  1. "new S"输入的时间更长。但"add""emplace"短。通过intellisense为您添加类型(只需在键入"new "后按 Enter ):
    1. 你害怕写错了。那么你不能用List<T>。 Intellisense将帮助您输入,编译器不允许在编译时添加错误的类型。

    2. 效果:请参阅@Xanatos answer

    3. list.Add(new S(1, "t"));完全可以使用。

      结论:我们emplace中不需要C#