Автоматическая инициализация свойств с анонимной функцией - PullRequest
0 голосов
/ 31 мая 2019

Я пытаюсь избавиться от некоторого кода с помощью анонимных функций и классов.

Я застрял на этом:

public List<Object> Years { get; set; } = GetYears();

private static List<Object> GetYears()
{
    List<Object> retList = new List<Object>();

    retList.Add(new { Value = (byte)255, Name = "Any" });
    retList.Add(new { Value = (byte)254, Name = "None" });

    for (byte i = 0; i < 50; i++)
    {
        retList.Add(new { Value = i, Name = (2000 + i).ToString() });
    }
    return retList;
}

Можно ли избавиться от статического GetYears ()method?

Я имею в виду что-то вроде этого:

public List<Object> Years { get; set; } = () =>  
{
    List<Object> retList = new List<Object>();
    for (byte i = 0; i < 50; i++)
    {
        retList.Add(new { Value = i, Name = (2000 + i).ToString() });
    }
    return retList;
}

Проблема в том, что инициализатор поля не может ссылаться на нестатический метод.

Возможно лиобойти это?

Редактировать: я добавил эти 2 строки кода:

retList.Add(new { Value = (byte)255, Name = "None" });
retList.Add(new { Value = (byte)254, Name = "Any" });

Ответы [ 2 ]

2 голосов
/ 31 мая 2019

Технически говоря, вы можете сделать что-то вроде этого

public class LambdaInitalization {
    public List<Object> Years = ((Func<List<Object>>)(() =>  
    {
        List<Object> retList = new List<Object>();
        for (byte i = 0; i < 50; i++)
        {
            retList.Add(new { Value = i, Name = (2000 + i).ToString() });
        }
        return retList;
    }))();
}

, которая создает анонимную функцию, которая возвращает List<Object>, а затем запускает ее (к сожалению, это не может быть подразумеваемо, это должно быть явное приведение).

Гораздо лучшим решением будет просто использовать конструктор, чтобы сделать в точности то, для чего существует конструктор.

public class CtorInitalization {
    public List<Object> Years { get; set; }

    public CtorInitalization() {
        Years = new List<Object>();
        for (byte i = 0; i < 50; i++)
        {
            Years.Add(new { Value = i, Name = (2000 + i).ToString() });
        }
    }
}

Как ни странно, инициализация lamda скомпилируется в конструкторе в любом случае , поэтому не существует действительного использования, функционально говоря, для определения его вне конструктора.

См. Оба в действии здесь: https://dotnetfiddle.net/1f62Hj

1 голос
/ 31 мая 2019

Как уже упоминалось, вы не можете сделать это специально, инициализатор не может ссылаться на нестатическое поле , метод или свойство 'field' , и анонимный метод - это не так.

Вы можете поместить его в конструктор, другие варианты будут сделать его Lazy<T>

public Lazy<List<Object>> Years { get; set; } = new Lazy<List<object>>(() =>
{
   List<object> retList = new List<object>();
   for (byte i = 0; i < 50; i++)
   {
      retList.Add(new { Value = i, Name = (2000 + i).ToString() });
   }
   return retList;
});

или взломать его немного с помощьюEnumerable.Range

private List<Object> Years { get; set; }
   = Enumerable.Range(0, 50)
               .Select(i => (object)new { Value = i, Name = (2000 + i).ToString() })
               .ToList();

Примечание : в целом List<object> кажется немного подозрительным

Или, может бытьчуть более кратким будет Value Tuple

private List<(int Value, string Name)> Years { get; set; }
   = Enumerable.Range(0, 50)
               .Select(i => (i, (2000 + i).ToString()))
               .ToList();
...