我按照此处的说明使用IEnumerable定义了一个集合初始化程序:http: //msdn.microsoft.com/en-us/library/bb384062.aspx
现在,我可以在我的集合初始化程序中创建对象,并使用我的Add()方法添加它们,如下所示:
class ArrangedPanel : RectElement
{
private List<RectElement> arrangedChildren = new List<RectElement>();
public int Padding = 2;
public void Add(RectElement element)
{
arrangedChildren.Add(element);
//do custom stuff here
}
public IEnumerator GetEnumerator()
{
return arrangedChildren.GetEnumerator();
}
}
// Somewhere
debugPanel.Add(new ArrangedPanel()
{
new ButtonToggle(),
new ButtonToggle()
});
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试设置属性,例如我的"填充"字段,我会在集合初始值设定项上出错.
debugPanel.Add(new ArrangedPanel()
{
Padding = 5,
new ButtonToggle(),
new ButtonToggle()
});
Run Code Online (Sandbox Code Playgroud)
是否可以设置集合初始化器和对象初始化器?
我想为练习实现一些不同的算法,只是为了看看我到底有多糟糕并且变得更好:p
无论如何,我以为我会尝试使用IEnumerable<T>和IOrderedEnumerable<T>其他.Net集合类型只是为了兼容(所以我写的东西以后可以更容易使用).
但我找不到一种方法来返回IOrderedEnumerable<T>除使用OrderBy和ThenBy扩展方法之外的其他实例.所以我想我必须创建自己的类来实现这个接口.但说实话,界面对我来说并不合理.它可能,但我不确定.
我创建了一个空类,添加了接口,然后让ReSharper为我添加空实现.它看起来像这样:
class MyOrderedEnumerable<T> : IOrderedEnumerable<T>
{
/// <summary>
/// Performs a subsequent ordering on the elements of an <see cref="T:System.Linq.IOrderedEnumerable`1"/> according to a key.
/// </summary>
/// <returns>
/// An <see cref="T:System.Linq.IOrderedEnumerable`1"/> whose elements are sorted according to a key.
/// </returns>
/// <param name="keySelector">The <see cref="T:System.Func`2"/> used to extract the key for each element.</param><param name="comparer">The <see cref="T:System.Collections.Generic.IComparer`1"/> used to compare keys for placement in the returned sequence.</param><param name="descending">true to sort …Run Code Online (Sandbox Code Playgroud) 有时检查不可重复 的内容是否有用,以查看IEnumerable它是否为空.LINQ Any对此不起作用,因为它消耗了序列的第一个元素,例如
if(input.Any())
{
foreach(int i in input)
{
// Will miss the first element for non-repeatable sequences!
}
}
Run Code Online (Sandbox Code Playgroud)
(注意:我知道在这种情况下没有必要进行检查 - 这只是一个例子!真实世界的例子是Zip对一个IEnumerable可能是空的右手执行.如果它是空的,我想要结果是左手IEnumerable原样.)
我想出了一个看起来像这样的潜在解决方案:
private static IEnumerable<T> NullifyIfEmptyHelper<T>(IEnumerator<T> e)
{
using(e)
{
do
{
yield return e.Current;
} while (e.MoveNext());
}
}
public static IEnumerable<T> NullifyIfEmpty<T>(this IEnumerable<T> source)
{
IEnumerator<T> e = source.GetEnumerator();
if(e.MoveNext())
{
return NullifyIfEmptyHelper(e);
}
else
{
e.Dispose();
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以按如下方式使用:
input = input.NullifyIfEmpty(); …Run Code Online (Sandbox Code Playgroud) 在我看来,很多扩展方法IList<T>都适用于IEnumerable<T>- 例如FindAll和RemoveAll.
谁能解释为什么他们不存在的原因?
我写了一个SplitBetween类似的LINQ扩展方法String.Split.
> new List<int>(){3,4,2,21,3,2,17,16,1}
> .SplitBetween(x=>x>=10)
[3,4,2], [3,2], [], [1]
Run Code Online (Sandbox Code Playgroud)
资源:
// partition sequence into sequence of contiguous subsequences
// behaves like String.Split
public static IEnumerable<IEnumerable<T>> SplitBetween<T>(this IEnumerable<T> source,
Func<T, bool> separatorSelector,
bool includeSeparator = false)
{
var l = new List<T>();
foreach (var x in source)
{
if (separatorSelector(x))
{
if (includeSeparator)
{
l.Add(x);
}
yield return l;
l = new List<T>();
}
else
{
l.Add(x);
}
}
yield return l;
}
Run Code Online (Sandbox Code Playgroud)
在LINQ的精神下,我认为这种方法应该做懒惰的评估.但是,我的实现对外部IEnumerable进行了懒惰的评估,但没有超过内部的IEnumerable …
对于我们来说,同一个可枚举的多次枚举是一个性能问题,所以我们尝试在代码中踩踏这些警告.但是我们有一个泛型扩展函数用于抛出生成大量这些警告的空参数异常.它的签名如下:
public static void VerifyArgumentIsNotNull<T>(this T value, string valueName) where T : class
Run Code Online (Sandbox Code Playgroud)
它所做的只是检查null并抛出一个格式良好的本地化(对于当时正在播放的人类语言)异常.
当此函数用于IEnumerable参数时,它会使代码分析警告IEnumerable可能的多次迭代,因为分析器不知道该函数的作用.
我想在这个函数上添加一些标记,"是的,这会将可枚举作为输入,但它不会迭代它,因此不应被调用者视为可能的迭代." 有没有这样的标签?我在互联网上搜索无济于事.
所有string.Split方法似乎都返回一个字符串数组(string[]).
我想知道是否有一个惰性变体返回一个IEnumerable<string>大字符串(或无限长度IEnumerable<char>),当一个人只对第一个子序列感兴趣时,一个节省计算工作量和内存.如果字符串由设备/程序(网络,终端,管道)构成,并且因此不需要立即完全可用,则它也可能是有用的.这样人们就已经可以处理第一次出现了.
.NET框架中是否有这样的方法?
假设我需要一个扩展方法,它只选择不同来源的必需属性.源可以是数据库或内存中的集合.所以我定义了这样的扩展方法:
public IQueryable<TResult> SelectDynamic<TResult>(
this IQueryable<T> source,
...)
Run Code Online (Sandbox Code Playgroud)
这适用于IQueryables.但是,我也必须为IEnumerables 调用此函数.
在这种情况下,我可以在以下帮助下调用它.AsQueryable():
myEnumerable.AsQueryable()
.SelectDynamic(...)
.ToList();
Run Code Online (Sandbox Code Playgroud)
两者都很好.我有这样的问题,如果两者都工作正常,在哪些情况下我必须为同一目的创建两个不同的扩展方法,一个与之合作IEnumerable,另一个与IQueryable?
我的方法必须在以下情况下向数据库发送查询Queryable.
例如,以下是命名空间.Select 内的扩展方法的来源System.Linq:
我再次重复我的主要问题:
我的方法必须发送查询到数据库Queryable,但不是在使用时IEnumerable.而就目前而言,我正在使用AsQueryable()枚举器.因为,我不想为此编写相同的代码Enumerable.可以有一些副作用吗?
我有一个Employee定义如下的类:
Employee
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime WorkDate { get; set; }
public bool isOff { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是我的类实现和用法:
List<Employee> workers = new List<Employee>()
{
new Employee { Id = 1, Name = "Emp 1", WorkDate = Convert.ToDateTime("4/11/2016"), IsOff = false},
new Employee { Id = 1, Name = "Emp 1", WorkDate = Convert.ToDateTime("4/12/2016"), IsOff = false},
new Employee { Id = 1, Name …Run Code Online (Sandbox Code Playgroud) 我注意到从IDataReader使用声明中读取一些我无法理解的好奇心.虽然我确信答案很简单.
为什么在内部using (SqlDataReader rd) { ... }如果我直接执行一个yield return阅读器在阅读期间保持打开状态.但是,如果我执行直接return调用SqlDataReader扩展方法(如下所述),读者在枚举可以实现之前关闭?
public static IEnumerable<T> Enumerate<T>(this SqlDataReader rd)
{
while (rd.Read())
yield return rd.ConvertTo<T>(); //extension method wrapping FastMember
rd.NextResult();
}
Run Code Online (Sandbox Code Playgroud)
为了完全清楚我在问什么,我不确定为什么以下内容根本不同:
一个充实的例子,根据@ TimSchmelter的要求:
/*
* contrived methods
*/
public IEnumerable<T> ReadSomeProc<T>() {
using (var db = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("dbo.someProc", db);
using(var rd = cmd.ExecuteReader())
{
while(rd.Read())
yield return rd.ConvertTo<T>(); //extension method wrapping FastMember
}
}
}
//vs
public IEnumerable<T> ReadSomeProcExt<T>() …Run Code Online (Sandbox Code Playgroud) c# ×10
ienumerable ×10
linq ×4
.net ×3
.net-4.0 ×1
ado.net ×1
c#-4.0 ×1
collections ×1
enumerable ×1
enumerator ×1
interface ×1
iqueryable ×1
resharper ×1
string ×1
yield-return ×1