Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XPathNodeIterator should implement IEnumerable<XPathNavigator> #14515

Closed
krwq opened this issue Apr 30, 2015 · 12 comments
Closed

XPathNodeIterator should implement IEnumerable<XPathNavigator> #14515

krwq opened this issue Apr 30, 2015 · 12 comments
Assignees
Labels
api-needs-work API needs work before it is approved, it is NOT ready for implementation area-System.Xml help wanted [up-for-grabs] Good issue for external contributors
Milestone

Comments

@krwq
Copy link
Member

krwq commented Apr 30, 2015

Currently XPathNodeIterator implements only IEnumerable interface. XPathNodeIterator always iterates over objects of type XPathNavigator and thus every usage ends up with casting back and forth XPathNavigator --> object --> XPathNavigator in a loop. Implementing IEnumerable on this type would allow to avoid this indirection and in cases where iterating is useful improve perf.

cc: @tmat

EDIT 2017/12/28: In PR: dotnet/corefx#26083

Requested API changes:

namespace System.Xml.XPath
{
...
-    public abstract class XPathNodeIterator : ICloneable, IEnumerable
+    public abstract class XPathNodeIterator : ICloneable, IEnumerable<XPathNavigator>
...
@krwq krwq self-assigned this Apr 30, 2015
@karelz karelz unassigned krwq Oct 10, 2016
@kassemsandarusi
Copy link
Contributor

kassemsandarusi commented Dec 23, 2017

I have a few questions about this. When playing around with implementing this, I noticed that the ApiCompat tool started to fail.

My understanding is that even though the GetEnumerator method (public virtual IEnumerable<XPathNodeIterator> GetEnumerator()) has technically changed, it should not break any existing code that is expecting a non-generic IEnumerable to be returned.

  1. Is this actually breaking .NET Standard API Compatibility? Am I missing something?
  2. I can technically make the original non-generic GetEnumerator method the one that is not fully qualified in order to ensure API compatibility, but does that not seem to defeat the purpose?
    • example change IEnumerator<XPathNodeIterator> IEnumerable<XPathNodeIterator>.GetEnumerator() and public virtual IEnumerator GetEnumerator().

My terminology use may be a bit primitive so I apologize in advance.

@svick
Copy link
Contributor

svick commented Dec 25, 2017

@kassemsandarusi

It is a breaking change according to corefx breaking change rules.

Consider for example this code:

void M(XPathNodeIterator iterator) => PrintType(iterator.GetEnumerator());

void PrintType<T>(T ignored) => Console.WriteLine(typeof(T));

Before the change, it would print System.Collections.IEnumerator, after it, it would print System.Collections.Generic.IEnumerator`1[System.Xml.XPath.XPathNavigator].

Even worse, the method is virtual, so it would break any inheritors that override that method.

I think what you need is to leave the existing GetEnumerator() method as is and implement the interface explicitly (which is what you mention in point 2). I think it does not defeat the purpose of this change: any APIs what work with IEnumerable<T> will start working (including LINQ). It won't enable foreach (var x in iterator) to work well, but I don't think that's possible without making a breaking change.

@kassemsandarusi
Copy link
Contributor

@svick That reference doc for breaking rule changes is incredibly useful. And in general, thanks for your advice on this issue.

@karelz
Copy link
Member

karelz commented Dec 28, 2017

@krwq what is the API shape? Please add formal API proposal (see the example there).

@krwq
Copy link
Member Author

krwq commented Dec 28, 2017

@karelz, I thought the title was enough but adding for clarity

@krwq krwq self-assigned this Dec 28, 2017
@karelz
Copy link
Member

karelz commented Dec 28, 2017

@krwq we should probably keep the IEnumerable as explicit interface -- I think there are subtle differences in explicitly / implicitly implemented interfaces.
Can you please add some justification to the top post? For people who don't have deep background in XML.

@krwq
Copy link
Member Author

krwq commented Dec 28, 2017

@karelz done

@terrajobst
Copy link
Member

terrajobst commented Jan 2, 2018

Video

Implementing IE<X> additionally would be fine, but this doesn't buy you anything for avoiding the cast in the foreach scenario as the compiler will still call through the existing non-generic GetEnumerator() method.

Am I missing anything?

@karelz
Copy link
Member

karelz commented Jan 2, 2018

FYI: The API review discussion was recorded - see https://youtu.be/dOpH6bUNbcw?t=1567 (8 min duration)

@kassemsandarusi
Copy link
Contributor

@karelz Based on the conversation it sounds like the PR should be closed out till the api is approved. Does this sound correct?

@karelz
Copy link
Member

karelz commented Jan 3, 2018

Sounds like a very reasonable plan, if you don't mind. Sorry for the confusion.

@krwq
Copy link
Member Author

krwq commented Sep 4, 2018

Since the interface has to be implemented explicitly there will be no gain for existing apps from this work and little discoverability for new apps - I will close this issue for now - please reopen/comment if your app/library will gain anything from this work and we will reconsider given new data.

@krwq krwq closed this as completed Sep 4, 2018
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 3.0 milestone Jan 31, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Jan 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-needs-work API needs work before it is approved, it is NOT ready for implementation area-System.Xml help wanted [up-for-grabs] Good issue for external contributors
Projects
None yet
Development

No branches or pull requests

6 participants