我注意到我有一些重复的代码。如何以更通用的方式完成这项工作?
班级结构是
class BaseObject
class MyBlock1 : BaseObject
class MyBlock2 : BaseObject
class MyBlock3 : BaseObject
循环是:
private List<MyBlock1> GetVideosSection(IEnumerable<ContentAreaItem> items)
{
List<MyBlock1> blocks = null;
if (items != null)
{
blocks = new List<MyBlock1>();
foreach (var reference in items)
{
var block = _repo.Get<MyBlock1>(reference.ContentLink);
blocks.Add(block);
}
}
return blocks;
}
对BaseObject
的每个实现重复循环。
items
参数是一个&#39;列表&#39;引用&#39; ID&#39;用于查找并返回适当对象。
我的尝试是按照
的方式进行的private List<T> GetBlocks<T>(IEnumerable<ContentAreaItem> items) where T : BlockData, new ()
{
List<BaseObject> blocks = null;
if (items != null)
{
T typeDeclaredInMethod = T from GetBlocks<T>;
blocks = new List< typeDeclaredInMethod >();
foreach (var reference in items)
{
var block = _repo.Get< typeDeclaredInMethod >(reference.ContentLink);
blocks.Add(block);
}
}
return blocks;
}
我意识到上面的代码无效,但有说明我的意图。
我是C#的新手,不知道泛型方法是如何工作的,所以不确定这是否可行。
如何编写此循环以适用于BaseObject
的所有实现?
我正在寻找的例子:
List<MyBlock1> block1List = GetBlocks<MyBlock1>( items );
List<MyBlock2> block2List = GetBlocks<MyBlock2>( items );
List<MyBlock3> block3List = GetBlocks<MyBlock3>( items );
或
List<BaseObject> block1List = GetBlocks<MyBlock1>( items );
答案 0 :(得分:2)
您的代码已关闭但您无需获取T
,您已经拥有它:
private List<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items)
{
List<T> blocks = null;
if (items != null)
{
blocks = new List<T>();
foreach (var reference in items)
{
var block = _repo.Get<T>(reference.ContentLink);
blocks.Add(block);
}
}
return blocks;
}
我会写如下:
private List<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items) => items?.Select(reference => _repo.Get<T>(reference.ContentLink)).ToList();
答案 1 :(得分:1)
让我们首先说明如何进行概括。我们从:
开始private List<MyBlock1> GetVideosSection(IEnumerable<ContentAreaItem> items)
{
List<MyBlock1> blocks = null;
if (items != null)
{
blocks = new List<MyBlock1>();
foreach (var reference in items)
{
var block = _repo.Get<MyBlock1>(reference.ContentLink);
blocks.Add(block);
}
}
return blocks;
}
我们希望对此进行参数化以消除MyBlock1
,因此我们只需声明一个新的类型参数 T并搜索并替换MyBlock1
:
private List<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items)
{
List<T> blocks = null;
if (items != null)
{
blocks = new List<T>();
foreach (var reference in items)
{
var block = _repo.Get<T>(reference.ContentLink);
blocks.Add(block);
}
}
return blocks;
}
我们完成了吗?我们完成了原始任务,但总是借此机会询问您是否可以做得更好。这种方法可以改进吗?当然。例如,我们可以注意到“接受并返回null”的合同是可怕的。这是容易出错和错误的。空序列便宜。不要将null视为空序列。既不接受也不归还。
private List<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items)
{
if (items == null) throw new ArgumentNullException("items");
List<T> blocks = new List<T>();
foreach (var reference in items)
{
var block = _repo.Get<T>(reference.ContentLink);
blocks.Add(block);
}
return blocks;
}
好多了。我们完了吗?不。我们现在看到我们的循环只是一个选择:
private List<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items)
{
if (items == null) throw new ArgumentNullException("items");
var query = from reference in items
select _repo.Get<T>(reference.ContentLink);
return query.ToList();
}
或者如果您愿意
private List<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items)
{
if (items == null) throw new ArgumentNullException("items");
return items.Select(reference => _repo.Get<T>(reference.ContentLink)
.ToList();
}
我们还能做得更好吗?在C#7中,我们可以在条件表达式的主体中放置一个表达式的方法:
private List<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items) =>
items == null ?
throw new ArgumentNullException("items") :
items.Select(reference => _repo.Get<T>(reference.ContentLink)
.ToList();
现在我们可能会问自己,我们真的需要ToList吗?如果调用者想要使用Where
进一步过滤结果,该怎么办?将其列为清单还为时过早:
private IEnumerable<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items) =>
items == null ?
throw new ArgumentNullException("items") :
items.Select(reference => _repo.Get<T>(reference.ContentLink));
或者如果您愿意:
private IEnumerable<T> GetVideosSection<T>(IEnumerable<ContentAreaItem> items) =>
items == null ?
throw new ArgumentNullException("items") :
from reference in items select _repo.Get<T>(reference.ContentLink);
如果来电者想要一个列表,那么他们可以说GetVideosSection<Whatever>(items).ToList()
,嘿,他们有一个列表。
看看与原始代码相比简洁易懂。原始代码说“这个方法最重要的是我用这个循环填写的列表”。此版本的代码强调了含义:我从与每个项目相关联的仓库中提取内容。