Дженерикам C# по сравнению с шаблонами C++ - нужно разъяснение об ограничениях

Вы можете использовать mongodb aggregation pipeline для достижения того же. Более конкретно, вы можете использовать $lookup дважды для заполнения parent и его parent и, наконец, $project для выравнивания структуры.

Попробуйте это:

Category.aggregation([{
    $lookup : {
        from :"categories",
        localField : "parent",
        foreignField : "_id",
        as  :"parent"
    }
},{
    $unwind : "$parent"
},{
    $lookup : {
        from :"categories",
        localField : "parent.parent",
        foreignField : "_id",
        as  :"parent.parent"
    }
},{
    $unwind : "$parent.parent"
},{
    $project : {
        l1_id  : "

Вы можете использовать mongodb aggregation pipeline для достижения того же. Более конкретно, вы можете использовать $lookup дважды для заполнения parent и его parent и, наконец, $project для выравнивания структуры.

Попробуйте это:

[110]

Примечание: $unwind используется после этапа $lookup, так как $lookup возвращает массив, нам нужно его развернуть преобразовать его в объект.

Для получения дополнительной информации, пожалуйста, прочитайте Mongodb $ lookup документов и $ проектной документации .

Надеюсь, это поможет вам.

id", l1_name : "$name", l2_id : "$parent._id", l2_name : "$parent.name" , l3_id : "$parent.parent._id", l2_name : "$parent.parent.name" } }]).then(result => { // result will have l1_id, l1_name, l2_id, l2_name, l3_id, l3_name // where l2 is the parent, // and l3 is the parent of parent }).

Примечание: $unwind используется после этапа $lookup, так как $lookup возвращает массив, нам нужно его развернуть преобразовать его в объект.

Для получения дополнительной информации, пожалуйста, прочитайте Mongodb $ lookup документов и $ проектной документации .

Надеюсь, это поможет вам.

11
задан Community 23 May 2017 в 10:31
поделиться

5 ответов

Ну, в общем, шаблоны C ++ и дженерики C # похожи - по сравнению с дженериками Java, которые полностью отличаются, но они также имеют большие различия. Как и в C #, существует поддержка времени выполнения с помощью отражения, получая объект, описывающий типы, используемые для создания экземпляров обобщений. C ++ не имеет отражения, и все, что он делает с типами, делается во время компиляции.

Самое большое различие между шаблонами C # и шаблонами C ++ заключается в том, что шаблоны C # лучше проверяются на тип. Они всегда ограничены в том смысле, что они не допускают операций, которые не указаны как действительные во время определения обобщений. Главный дизайнер C # поднял в качестве причины того, что дополнительная сложность, которую он взял бы, подразумевала ограничения. Я не очень разбираюсь в C #, поэтому я не могу говорить здесь дальше. Я расскажу о том, как обстоят дела в C ++ и как они будут улучшаться, чтобы люди не думали, что все в C ++ неправильно.

В C ++ шаблоны не ограничены. Если вы выполняете операцию, то во время определения шаблона подразумевается, что операция завершится успешно во время создания экземпляра. Это' даже компилятору C ++ не требуется, чтобы шаблон синтаксически проверялся на достоверность. Если он содержит синтаксическую ошибку, то эта ошибка должна быть диагностирована при создании экземпляра. Любая диагностика до этого является чистой полезностью реализации.

Эти подразумеваемые ограничения оказались простыми для дизайнера шаблонов в краткосрочной перспективе, потому что им не нужно заботиться об указании допустимых операций в их интерфейсе шаблона. Они ложатся бременем на пользователя своего шаблона - поэтому пользователь должен убедиться, что он выполняет все эти требования. Часто случается, что пользователь пытается выполнить, казалось бы, допустимые операции, но терпит неудачу, при этом компилятор выдает пользователю сотни строк сообщений об ошибках о каком-то неверном синтаксисе или не найденных именах. Потому что компилятор может Не знаю , какое именно ограничение было нарушено в первую очередь, в нем перечислены все части путей кода, когда-либо задействованных вокруг неисправного места, и все, даже не важные детали, и пользователь должен будет пролистать эту ужасную ошибку текст сообщения.

Это фундаментальная проблема, которую можно решить, просто указав в интерфейсе шаблон или шаблон, какие свойства должен иметь параметр типа. Насколько я знаю, C # может ограничивать параметр для реализации интерфейса или наследования базового класса. Это решает это на уровне типа.

Комитет C ++ уже давно видел, что необходимо решить эти проблемы, , и вскоре (вероятно, в следующем году), C ++ также сможет сформулировать такие явные ограничения ( см. Time- примечание машины ниже ), как и в следующем случае.

template<typename T> requires VariableType<T>
T f(T a, T b) {
    return a + b; 
}

В этот момент компилятор сообщает об ошибке, поскольку записанное выражение не помечено как допустимое в соответствии с требованиями. Это сначала помогает разработчику шаблона написать больше правильного кода , потому что код уже проверен на тип уже в некоторой степени (хорошо, что там возможно). Теперь программист может заявить, что это требование:

template<typename T> requires VariableType<T> && HasPlus<T, T>
T f(T a, T b) {
    return a + b; 
}

Теперь это будет компилятор. Компилятор, увидев T в качестве возвращаемого типа, автоматически подразумевает, что T является копируемым, потому что это использование T появляется в интерфейсе, а не в тело шаблонов. Другие требования были изложены с использованием положений требований. Теперь пользователь получит соответствующее сообщение об ошибке, если он использует тип, для которого не определено op + .

C ++ 1x отделяет требования от типа. Вышесказанное работает как для примитивных типов, так и для классов. В этом смысле они более гибкие, но довольно сложные. Правила, которые определяют, когда и когда выполняются требования, длинные ... Вы можете с помощью новых правил сказать следующее:

template<typename T> requires MyCuteType<T>
void f(T t) { *t = 10; }

А затем вызвать f с int ! Это сработало бы, просто написав концептуальную карту для MyCuteType , которая учит компилятору, как можно ссылаться на int. Это будет очень удобно в таких циклах:

for_each(0, 100, doSomething());

Поскольку программист может сообщить компилятору, как int может удовлетворить концепцию итератора ввода , вы могли бы написать такой код на C ++ 1x, если вы только напишите соответствующую концептуальную карту, что на самом деле не так уж сложно.

Хорошо, хватит с этим. Я надеюсь, что смогу показать вам, что ограничение шаблонов не так уж и плохо, но на самом деле лучше , потому что отношения между типами и операциями с ними в шаблонах теперь известны компилятору. И я даже не написал об аксиомах , которые являются еще одной приятной вещью в концепциях C ++ 1x . Помните, что это будущие вещи , они еще не вышли, но примерно в 2010 году. Тогда нам нужно будет подождать, пока какой-нибудь компилятор реализует все это:)


ОБНОВЛЕНИЕ ОТ "БУДУЩЕГО"

Концепции C ++ 0x не были приняты в проект, но были отклонены в конце 2009 года. Очень жаль! Но, возможно, мы увидим это снова в следующей версии C ++? Давайте все будем надеяться!

потому что отношения между типами и операциями над ними в шаблонах теперь известны компилятору. И я даже не написал об аксиомах , которые являются еще одной приятной вещью в концепциях C ++ 1x . Помните, что это будущие вещи , они еще не вышли, но примерно в 2010 году. Тогда нам нужно будет подождать, пока какой-нибудь компилятор реализует все это:)


ОБНОВЛЕНИЕ ОТ "БУДУЩЕГО"

Концепции C ++ 0x не были приняты в проект, но были отклонены в конце 2009 года. Очень жаль! Но, возможно, мы увидим это снова в следующей версии C ++? Давайте все будем надеяться!

потому что отношения между типами и операциями над ними в шаблонах теперь известны компилятору. И я даже не написал об аксиомах , которые являются еще одной приятной вещью в концепциях C ++ 1x . Помните, что это будущие вещи , они еще не вышли, но это будет примерно в 2010 году. Тогда нам нужно будет подождать, пока какой-то компилятор реализует все это:)


ОБНОВЛЕНИЕ ОТ "БУДУЩЕГО"

Концепции C ++ 0x не были приняты в проект, но были отклонены в конце 2009 года. Очень жаль! Но, возможно, мы увидим это снова в следующей версии C ++? Давайте все будем надеяться!

это еще одна приятная вещь в концепциях C ++ 1x . Помните, что это будущие вещи , они еще не вышли, но это будет примерно в 2010 году. Тогда нам нужно будет подождать, пока какой-то компилятор реализует все это:)


ОБНОВЛЕНИЕ ОТ "БУДУЩЕГО"

Концепции C ++ 0x не были приняты в проект, но были отклонены в конце 2009 года. Очень жаль! Но, возможно, мы увидим это снова в следующей версии C ++? Давайте все будем надеяться!

это еще одна приятная вещь в концепциях C ++ 1x . Помните, что это будущие вещи , они еще не вышли, но это будет примерно в 2010 году. Тогда нам нужно будет подождать, пока какой-то компилятор реализует все это:)


ОБНОВЛЕНИЕ ОТ "БУДУЩЕГО"

Концепции C ++ 0x не были приняты в проект, но были отклонены в конце 2009 года. Очень жаль! Но, возможно, мы увидим это снова в следующей версии C ++? Давайте все будем надеяться!

Но, возможно, мы увидим это снова в следующей версии C ++? Давайте все будем надеяться!

Но, возможно, мы увидим это снова в следующей версии C ++? Давайте все будем надеяться!

20
ответ дан 3 December 2019 в 03:19
поделиться

Шаблоны C ++: Компилятор проверяет, удовлетворяют ли аргументы ограничениям, установленным кодом. Например:

template <typename T, unsigned int dim>
class math_vector
{
    T elements[dim];

    math_vector<T,dim> operator+ (const math_vector<T,dim>& other) const
    {
        math_vector<T,dim> result;
        for (unsigned int i = 0; i < dim; ++i)
            result.elements[i] = elements[i] + other.elements[i];
    }
}

struct employee
{
    char name[100];
    int age;
    float salary;
}

math_vector<int, 3> int_vec; //legal
math_vector<float, 5> float_vec; //legal
math_vector<employee, 10> employee_vec; //illegal, operator+ not defined for employee

В этом примере вы можете создать класс, определить для него оператор + и использовать его в качестве параметра для math_vector . Следовательно, параметр шаблона действителен тогда и только тогда, когда он удовлетворяет ограничениям, определенным кодом шаблона. Это очень гибкий, но приводит к длительному времени компиляции (должен ли тип проверяться каждый раз, когда создается экземпляр шаблона).

C # generics: Вместо проверки достоверности каждого конкретного экземпляра, что приводит к увеличению времени компиляции. и подвержен ошибкам, вы явно заявляете, что аргументы универсального шаблона должны реализовывать определенный интерфейс (набор методов, свойств и операторов). Внутри общего кода вы не можете свободно вызывать любые методы, но только те, которые поддерживаются этим интерфейсом. Каждый раз, когда вы создаете экземпляр generic, среда выполнения не должна проверять, удовлетворяет ли аргумент длинному набору ограничений, а только реализует ли он указанный интерфейс. Конечно, это менее гибко, но и менее подвержено ошибкам. Пример:

class SortedList<T> where T : IComparable<T>
{
    void Add(T i) { /* ... */ }
}

class A : IComparable<A> { /* ... */ }

class B
{
    int CompareTo(B b) { /* ... */ }
    bool Equals(B b) { /* ... */ }
}

SortedList<A> sortedA; // legal
SortedList<B> sortedB; // illegal
// B implements the methods and properties defined in IComparable,
// however, B doesn't explicitly implement IComparable<B>
4
ответ дан 3 December 2019 в 03:19
поделиться

В ближайшее время вы получите лучший ответ, я уверен. В то время я удалю этот.

Разница в том, что шаблоны в C ++ похожи на макросы. Именно когда создается экземпляр шаблона, код компилируется, и ошибки компиляции отображаются, если неявные ограничения нарушаются. Именно так вы можете создавать шаблонные специализации - шаблон в основном уже расширен специализацией, поэтому он и используется.

Обобщения в .NET (также в VB.NET) являются конструкцией времени выполнения. Это особый тип. Ограничения необходимы для того, чтобы гарантировать, что любое фактическое использование типа будет действительным, когда тип, наконец, используется.

На самом деле вы можете использовать Reflection для просмотра универсального типа и найти параметры типа, используемые для его создания, или посмотреть универсальное определение и увидеть ограничения для каждого параметра типа. В C ++ эта информация уже исчезла во время выполнения.

3
ответ дан 3 December 2019 в 03:19
поделиться

Шаблон и дженерики - это действительно разные вещи. Одна из целей дженериков заключается в том, чтобы иметь возможность использовать их в кросс-библиотеке, кросс-языковой, что не совпадает с шаблонами C ++. Они представляют собой концепцию CLR, а не концепцию языка (хотя они, очевидно, нуждаются в языковой поддержке).

В C ++ шаблоны можно рассматривать как «макросы на стероидах» (не пламя, пожалуйста, я знаю, что шаблоны не являются макросами). ), потому что вы можете видеть их как текстовое расширение, которое затем компилируется. Это дает им возможность использовать все, что определено в параметре шаблона (в основном, например, операторы), потому что ограничения налагаются кодом, использующим их.

В .NET, поскольку обобщенные типы разрешаются (создаются) во время выполнения, ограничение должно быть наложено на уровне определения, чтобы компилятор мог гарантировать, что их использование будет допустимым (что означает, что вы не можете использовать операторы для параметров универсальных параметров, потому что вы не можете указать ограничение для существования оператора).

Как я Сказано, что главное в дженериках - это возможность создавать дженерики для использования в других проектах. Вот почему они разные.

0
ответ дан 3 December 2019 в 03:19
поделиться

Обобщения C # полностью отличаются от C ++.

В C # компилятор в основном компилирует одно определение класса для всего объекта типов и определения класса для каждого типа значения.

В C ++ каждый тип получает свои собственные определения классов.

Ограничения предназначены только для компилятора, поэтому вы можете делать выводы из других мест.

Я бы порекомендовал рассмотрим делегаты Action, Func и Predicate и связанные методы расширения IEnumerable. Используйте лямбда-функции с ними, и вы увидите, что делают ограничения.

1
ответ дан 3 December 2019 в 03:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: