Фактически возможно вернуть анонимный тип из метода в конкретном случае использования. Давайте посмотрим!
В C # 7 можно возвращать анонимные типы из метода, хотя это имеет небольшое ограничение. Мы собираемся использовать новую языковую функцию, называемую локальной функцией, вместе с трюком косвенного обращения (другой уровень косвенного обращения может решить любую проблему программирования, верно?).
Вот пример использования, который я недавно обнаружил. Я хочу регистрировать все значения конфигурации после их загрузки из AppSettings
. Зачем? Потому что есть некоторая логика вокруг пропущенных значений, которые возвращаются к значениям по умолчанию, некоторому синтаксическому анализу и так далее. Простой способ записать значения после применения логики - это поместить их все в класс и сериализовать в файл журнала (с помощью log4net). Я также хочу инкапсулировать сложную логику работы с настройками и отделить ее от всего, что мне нужно с ними делать. И все это без создания именованного класса, который существует только для одноразового использования!
Давайте посмотрим, как решить эту проблему с помощью локальной функции, которая создает анонимный тип.
public static HttpClient CreateHttpClient()
{
// I deal with configuration values in this slightly convoluted way.
// The benefit is encapsulation of logic and we do not need to
// create a class, as we can use an anonymous class.
// The result resembles an expression statement that
// returns a value (similar to expressions in F#)
var config = Invoke(() =>
{
// slightly complex logic with default value
// in case of missing configuration value
// (this is what I want to encapsulate)
int? acquireTokenTimeoutSeconds = null;
if (int.TryParse(ConfigurationManager.AppSettings["AcquireTokenTimeoutSeconds"], out int i))
{
acquireTokenTimeoutSeconds = i;
}
// more complex logic surrounding configuration values ...
// construct the aggregate configuration class as an anonymous type!
var c = new
{
AcquireTokenTimeoutSeconds =
acquireTokenTimeoutSeconds ?? DefaultAcquireTokenTimeoutSeconds,
// ... more properties
};
// log the whole object for monitoring purposes
// (this is also a reason I want encapsulation)
Log.InfoFormat("Config={0}", c);
return c;
});
// use this configuration in any way necessary...
// the rest of the method concerns only the factory,
// i.e. creating the HttpClient with whatever configuration
// in my case this:
return new HttpClient(...);
// local function that enables the above expression
T Invoke<T>(Func<T> func) => func.Invoke();
}
Мне удалось построить анонимный класс, а также инкапсулировать логику работы со сложным управлением настройками внутри CreateHttpClient
и внутри своего собственного «выражения». Возможно, это не совсем то, что хотел OP, но это легкий подход с анонимными типами, который в настоящее время возможен в современном C #.