Skip to content

Add List.From<T> factory method taking IEnumerable<T> where T : IValue #43

@dahlia

Description

@dahlia

The current signature of Bencodex.Types.List(IEnumerable<IValue>) constructor requires frequent type casting to IEnumerable<IValue>, because C# does not automatically infer G<T> where T : B to G<B>. For example, the following code fails to build:

int[] ints = { 1, 2, 3, 4 };
IEnumerable<Bencodex.Types.Integer> bInts =
    ints.Select(i => (Bencodex.Types.Integer)i);
var list = new Bencodex.Types.List(bInts);  // Type error

It's because IEnumerable<Bencodex.Types.Integer> cannot be passed to IEnumerable<IValue>, even though Bencodex.Types.Integer implements IValue. Instead, we need to explicitly cast bInts so that the code is compiled:

var list = new Bencodex.Types.List(bInts.Cast<IValue>());

This can be fixed by changing the parameter type from IEnumerable<IValue> instead of IEnumerable<T> where T : IValue. However, unfortunately .NET disallows constructors to have type parameters. Therefore, we need add a separate factory method instead:

public static List From<T>(IEnumerable<T> values)
    where T : IValue;

Or, we might be better to have extension methods on IEnumerable<T> where T : IValue instead:

public static class EnumerableExtensions
{
    public static Bencodex.Types.List ToBencodexList<T>(this IEnumerable<T> source)
        where T : IValue;
    public static Bencodex.Types.Dictionary ToBencodexDictionary<TKey, TValue>(
        this IEnumerable<KeyValuePair<TKey, TValue>> source
    )
        where TKey : IKEy
        where TValue : IValue;
}

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions