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

Con*_*tor 10 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");
Run Code Online (Sandbox Code Playgroud)

是否有的C++函数任何C#类似物像emplaceemplace_back容器类(System.Collections.Generic.List)?

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

xan*_*tos 5

一般来说,C#中没有任何类似的东西,它的需求远远低于C++.

在C#中,当你拥有一个List<SomeReferenceType>你真正拥有的是一个List<ReferenceToSomeType>引用列表时,每个元素的大小为4或8个字节(请参阅.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(最终只使用了放置构造函数).

  • @Constructor:如果在C++中所做的只是为你节省了一点点打字,它就不会存在,因为这肯定不是它的动机之一. (4认同)

Gru*_*ndy 4

您可以通过扩展稍微改进@Boo 变体您可以使用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));
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:没有检查类型和计数参数,所以如果你做错了什么,你只会在运行时得到错误