Add an item to the dictionary where the key is a value property

I am trying to create a dictionary where the key is a property of the value object. However, I would like to build a value object in the dictionary add method. Is there a way to do this without using an intermediate variable?

For example, I would like to do the following, but, of course, the key value is not available when necessary.

Dictionary<int,SomeComplexObject> dict = new Dicionary<int,SomeComplexObject>{
   {someComplexObject.Key, new SomeComplexObject {Key = 1, Name = "FooBar"},
   {someComplexObject.Key, new SomeComplexObject {Key = 2, Name = "FizzBang"} 
};

Should I do it ugly:

Dictionary<int,SomeComplexObject> dict = new Dicionary<int,SomeComplexObject>();
SomeComplexObject value1 = new SomeComplexObject{Key=1,Name = "FooBar"};
dict.Add(value1.Key,value1);
SomeComplexObject value2 = new SomeComplexObject{Key=2,Name = "FizzBang"};
dict.Add(value.Key,value2);

I do not think this is the same question as How to use the object identifier as a key for the dictionary <K, V>

because I don’t ask specifically about the dictionary key, but if there is a way to access the property of the objects when the object is not created until it appears in the list of method parameters.

+4
3

, , , , , . , , , , .

, , , ( ) , , . , , .

, , , Dictionary<TKey, TValue>, . , , , .

:

class KeyExtractorDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    private readonly Func<TValue, TKey> _extractor;

    public KeyExtractorDictionary(Func<TValue, TKey> extractor)
    {
        _extractor = extractor;
    }

    public void Add(TValue value)
    {
        Add(_extractor(value), value);
    }
}

:

class Data
{
    public int Key { get; }
    public string Name { get; }

    public Data(int key, string name)
    {
        Key = key;
        Name = name;
    }
}

class Program
{
    static void Main(string[] args)
    {
        KeyExtractorDictionary<int, Data> dictionary =
            new KeyExtractorDictionary<int, Data>(d => d.Key)
            {
                new Data(1, "FooBar"),
                new Data(2, "FizzBang")
            };
    }
}

( Data T, , , , .)

, , , . , .

, , , #. Add(), , .

, ( , ), - , .

+3

, :

public static void AddByKey<TKey, T>(this Dictionary<TKey, T> dictionary, T item)
{
    dictionary.Add(item.Key, item);
}

, , Key:

public interface ItemWithKey<TKey>
{
    TKey Key { get; }
}

public static void AddByKey<TKey, T>(this Dictionary<TKey, T> dictionary, T item)
    where T : ItemWithKey<TKey>
{
    dictionary.Add(item.Key, item);
}

, , . , , . , .

+1

, @pid, linq. , , . , , :

class Program
{
    static void Main(string[] args)
    {
        List<SomeComplexObject> toAdd = new List<SomeComplexObject>() {
        new SomeComplexObject(1,"FooBar"),
        new SomeComplexObject(2,"FizzBang")
        };
        var dict = new Dictionary<int,SomeComplexObject>();
        dict.AddByKey(toAdd, item => item.Key);
    }
}

AddByKey - , linq :

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

public static class DictionaryExtensions
{
    /// <summary>
    /// This extension method was built for when you want to add a list of items to a dictionary as the values, and you want to use one of those 
    /// items' properties as the key. It uses LINQ to check by property reference. 
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    /// <param name="dict"></param>
    /// <param name="targets"></param>
    /// <param name="propertyToAdd"></param>
    public static void AddByKey<TKey, TValue>(this Dictionary<TKey, TValue> dict, IEnumerable<TValue> targets, Expression<Func<TValue, TKey>> propertyToAdd)
    {
        MemberExpression expr = (MemberExpression)propertyToAdd.Body;
        PropertyInfo prop = (PropertyInfo)expr.Member;

        foreach (var target in targets)
        {
            var value = prop.GetValue(target);
            if (!(value is TKey))
                throw new Exception("Value type does not match the key type.");//shouldn't happen.
            dict.Add((TKey)value, target);
        }
    }
}

, void, , :

var dict = new Dictionary<int,SomeComplexObject>().AddByKey(toAdd, item => item.Key);
0

Source: https://habr.com/ru/post/1669968/


All Articles