gpt4 book ai didi

c# - 将不同类型的 Action 数组传递给方法

转载 作者:行者123 更新时间:2023-12-05 05:43:34 25 4
gpt4 key购买 nike

我有以下代码,它根据作为参数传递的值的类型存储要执行的操作列表...

Action<int> intAction = x => Console.WriteLine($"You sent an int: {x}");
Action<bool> boolAction = x => Console.WriteLine($"You sent a bool: {x}");

var funcsByInputType = new Dictionary<Type, Action<object>>();
funcsByInputType[typeof(int)] = (object x) => intAction((int)x);
funcsByInputType[typeof(bool)] = (object x) => boolAction((bool)x);

PerformAction(true);
PerformAction(42);

void PerformAction<TValue>(TValue value)
{
if (funcsByInputType!.TryGetValue(typeof(TValue), out Action<object>? action))
{
action(value!);
}
}

这按预期工作。

我现在想要做的是从我只调用一次的单个方法创建字典,这样我就可以像这样重写我的代码。

Action<int> intAction = x => Console.WriteLine($"You sent an int: {x}");
Action<bool> boolAction = x => Console.WriteLine($"You sent a bool: {x}");

funcsByInputType = MakeFuncsByInputType(intAction, boolAction);

PerformAction(true);
PerformAction(42);

void PerformAction<TValue>(TValue value)
{
if (funcsByInputType!.TryGetValue(typeof(TValue), out Action<object>? action))
{
action(value!);
}
}

如何编写 MakeFuncsByInputType 方法?

请注意,我不想多次调用该方法,也不想将我的参数定义为 params object[]

最佳答案

这是不可能的,因为通过 Action<object>作为 Action<string> 的别名我将能够通过 42而不是字符串。

所以我不得不改用构建器模式。

公共(public)静态部分类 Reducer{public static Builder New() => new Builder();

public class Builder<TState>
{
private bool Built;
private ImmutableArray<KeyValuePair<Type, Func<TState, object, Result<TState>>>> TypesAndReducers;

internal Builder() => TypesAndReducers = ImmutableArray.Create<KeyValuePair<Type, Func<TState, object, Result<TState>>>>();

public Builder<TState> Add<TDelta>(Func<TState, TDelta, Result<TState>> reducer)
{
if (reducer is null)
throw new ArgumentNullException(nameof(reducer));

EnsureNotBuilt();
TypesAndReducers = TypesAndReducers.Add(new(typeof(TDelta), (state, delta) => reducer(state, (TDelta)delta)));
return this;
}

public Func<TState, object, Result<TState>> Build()
{
EnsureNotBuilt();
if (TypesAndReducers.Length == 0)
throw new InvalidOperationException("Must add at least one reducer to build.");

Built = true;

var dictionary = TypesAndReducers
.GroupBy(x => x.Key)
.ToDictionary(x => x.Key, x => x.Select(x => x.Value));

return (TState state, object delta) =>
{
if (delta is null)
throw new ArgumentNullException(nameof(delta));

if (!dictionary.TryGetValue(delta.GetType(), out var reducers))
return (false, state);

bool anyChanged = false;
TState newState = state;
foreach(var reducer in reducers)
{
(bool changed, newState) = reducer(newState, delta);
anyChanged |= changed;
}

return anyChanged
? (true, newState)
: (false, state);
};
}

private void EnsureNotBuilt()
{
if (Built)
throw new InvalidOperationException("Reducer has already been built.");
}

}

关于c# - 将不同类型的 Action<T> 数组传递给方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71800311/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com