在构造函数中传递成员访问函数
Posted
技术标签:
【中文标题】在构造函数中传递成员访问函数【英文标题】:Passing a member-access function in the constructor 【发布时间】:2021-11-17 14:38:02 【问题描述】:假设我有一个类似的帮助类
public class Selection<T, W> : ISelection<T,W> where W : ICollection<T>
public Selection(Func<W> selectableItemsProvider)
...
由于 C# 不支持委托接口实现,我想我会为自己节省一些样板文件,只需扩展 Selection
类...
public class MyFoo : Selection<Blah, List<Blah>>
private List<Blah> _blahs = new List<Blah>();
public MyFoo() : base(() => _blahs)
...
除非我不能那样做,我可以吗,因为
无法在静态上下文中访问非静态属性“_blahs”
即使我已经知道在对象构造之后才会调用提供程序。
有没有办法解决这个问题,还是我坚持添加样板代码?
【问题讨论】:
添加受保护的空构造函数然后允许直接分配selectableItemsProvider
(例如使其成为受保护的成员)?
你的意思是不会在Selection
构造函数中调用提供者?
@Sweeper 完全正确。
我会按照@Evk 的建议去做:protected Func<W> SelectableItemsProvider get;
、protected Selection()
、public MyFoo() SelectableItemsProvider = () => _blahs;
@Evk 但是我不能再要求在对象实例化之后设置提供程序。
【参考方案1】:
一个有点迂回的方法是将每次返回相同列表的 lambda 传递给基类构造函数。然后调用那个 lambda 来初始化 blahs
:
public class Selection<T, W>: ISelection<T, W> where W : ICollection<T>
// assuming you have a property like this that is initialised by the constructor...
protected Func<W> SelectableItemsProvider get;
public Selection(Func<W> selectableItemsProvider)
SelectableItemsProvider = selectableItemsProvider;
public class MyFoo : Selection<Blah, List<Blah>>
private List<Blah> _blahs;
public MyFoo() : base(new List<Blah>().CaptureInFunc())
_blahs = SelectableItemsProvider();
CaptureInFunc
是一个扩展方法,声明如下:
public static Func<T> CaptureInFunc<T>(this T t) => () => t;
这为我们提供了一个 lambda,它每次都返回 t
。
【讨论】:
【参考方案2】:一种方法可能是首先引入基本抽象类。这个类将包含所有逻辑:
public abstract class SelectionBase<T, W> where W : ICollection<T>
protected SelectionBase()
protected abstract Func<W> GetSelectableItemsProvider();
然后更改您当前的Selection
以继承它并在构造函数中接受选择器,这就是整个实现:
public sealed class Selection<T, W> : SelectionBase<T, W> where W: ICollection<T>
private readonly Func<W> _selectableItemsProvider;
public Selection(Func<W> selectableItemsProvider)
_selectableItemsProvider = selectableItemsProvider;
protected override Func<W> GetSelectableItemsProvider()
return _selectableItemsProvider;
现在,如果您想以问题中提到的方式扩展选择:
public class SpecificSelection : SelectionBase<string, List<string>>
private List<string> _blah;
public SpecificSelection()
protected override Func<List<string>> GetSelectableItemsProvider()
return () => _blah;
【讨论】:
【参考方案3】:您不能在调用基本构造函数时引用“this”的成员,因为“this”还不存在。
我建议组合而不是继承。该类仍然可以实现与帮助程序相同的接口,然后将所有调用委托给真正的实现。
public class MyFoo : ISelection<Blah, List<Blah>>
private List<Blah> _blahs;
private ISelection<Blah, List<Blah>> _implementation;
public MyFoo()
_blahs = new List<Blah>();
_implementation = new Selection<Blah, List<Blah>>(() => _blahs);
public void DoSomethingWithSelection()
_implementation.DoSomethingWithSelection();
【讨论】:
以上是关于在构造函数中传递成员访问函数的主要内容,如果未能解决你的问题,请参考以下文章
如何将双精度向量传递给构造函数,然后在子类中访问其数据(在 C++ 中)?
GroovyGroovy 方法调用 ( Groovy 构造函数中为成员赋值 | Groovy 函数的参数传递与键值对参数 | 完整代码示例 )