开发者

accessing C# base class in iterator causes ReSharper warning

开发者 https://www.devze.com 2023-01-04 20:47 出处:网络
I have two classes, GenericList and SpecificList, where SpecificList inherits from GenericList.GenericList implements IEnumerable<GenericItem> and SpecificList implements IEnumerable<Specific

I have two classes, GenericList and SpecificList, where SpecificList inherits from GenericList. GenericList implements IEnumerable<GenericItem> and SpecificList implements IEnumerable<SpecificItem>. SpecificItem inherits from GenericItem. I have to implement GetEnumerator in both GenericList and SpecificList since they implement IEnumerable<T>. In GenericList, it's easy enough, I just return the enumerator for the underlying List<T>:

public IEnumerator<GenericItem> GetEnumerator()
{
    return genericItemsList.GetEnumerator();
}

However, in SpecificList, it seems trickier. It seems risky to cast IEnumerator<GenericItem> to IEnumerator<SpecificItem>, and I don't know if that would even work. Instead, I did the following:

public new IEnumerator<SpecificItem> GetEnumerator()
{
    IEnumerator<GenericItem> enumerator = base.GetEnumerator();
    while (enumerator.MoveNext())
    {
        yield return (SpecificItem)enumerator.Current;
    }
}

This compiles fine and a simple MSTest unit test calling SpecificList.GetEnumerator() seems to show it works. However, ReSharper highlights base in the above method with the following warning:

Access to GenericList.GetEnumerator through 'base' keywo开发者_C百科rd from anonymous method, lambda expression, query expression or iterator results in unverifiable code

Is this something I should worry about? Should I do something differently?

Edit: I'm using ReSharper 5.1 Full Edition Pre-Release Build 5.1.1715.35.

Also, I should take a break from running MSTest unit tests: I just hit Ctrl+R, Ctrl+T in Chrome to reload the page...


R# is correct that accessing the base keyword inside an iterator / lambda in the 3.0 version of the C# compiler could result in unverifiable code. When it does or doesn't is a bit complex and I won't attempt to cover it here.

The easiest way to work around this is to wrap the call to base.GetEnumerator in another non-static private method and reference that from your iterator.

private IEnumerator<GenericItem> GetBaseEnumerator() {
  return base.GetEnumerator();
}

public new IEnumerator<SpecificItem> GetEnumerator()
{
    IEnumerator<GenericItem> enumerator = GetBaseEnumerator();
    while (enumerator.MoveNext())
    {
        yield return (SpecificItem)enumerator.Current;
    }
}

I'm fairly certain this bug was fixed in the 4.0 version of the C# compiler.


It seems risky to cast IEnumerator<GenericItem> to IEnumerator<SpecificItem>, and I don't know if that would even work.

Sure it would.

return base.Cast<SpecificItem>().GetEnumerator();

No more or less risky than your current implementation. In fact, I'm pretty sure it's more-or-less the same code under the hood.

0

精彩评论

暂无评论...
验证码 换一张
取 消