How does NEST (C#) implicitly convert types?

Viewed 479

I am looking at NEST library for the Elasticsearch. Trying to create something similar.

But can't understand how they do implicit type conversion in the QueryBase.cs:

private static QueryBase Combine(QueryBase leftQuery, QueryBase rightQuery, Func<QueryContainer, QueryContainer, QueryContainer> combine)
{
    if (IfEitherIsEmptyReturnTheOtherOrEmpty(leftQuery, rightQuery, out var q))
        return q;

    IQueryContainer container = combine(leftQuery, rightQuery);
    var query = container.Bool;
    return new BoolQuery
    {
        Must = query.Must,
        MustNot = query.MustNot,
        Should = query.Should,
        Filter = query.Filter,
    };
}

Func<QueryContainer, QueryContainer, QueryContainer> combine was passed as an argument and it expects QueryContainer objects as parameter. But later when we call, we give leftQuery object which is type of QueryBase.

IQueryContainer container = combine(leftQuery, rightQuery);

Why this works, what am I missing here? I can't find any relationship between QueryContainer and QueryBase.

2 Answers

As @Severius5 said in the comment, the answer is here in the line 112:

public static implicit operator QueryContainer(QueryBase query) =>
            query == null ? null : new QueryContainer(query);

Basically, it called implicit user-defined type conversion operator. Thank you very much.

You can read more documentation

NEST makes use of implicit conversions in several places, with the aim of making the API easy to use whilst at the same time leveraging type safety.

All queries implicitly convert to QueryContainer through the implicit operator conversion from QueryBase (the base type that all queries inherit from) to QueryContainer. To understand why this is done, consider the form of a query within Elasticsearch's JSON DSL

{
    "query" : {
        "<QUERY TYPE>" : {
            // ...
        }
    }
}

Within NEST, there is a query type for each QUERY TYPE, which is a field name within a JSON object. The QueryContainer type represents that object in which the query is defined.

Other places where implicit conversions are used are typically where

  1. A field may take multiple different formats within the JSON DSL, and so the NEST API exposes this through a specialized type
  2. The JSON DSL may accept a primitive value for a field e.g. a string value, but the NEST API wishes to impose some form of validation or specialized serialization.
Related