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

ItemsSourceView.IndexOf API spec #74

Merged
merged 14 commits into from
Apr 4, 2020

Conversation

marcelwgn
Copy link
Contributor

This PR will add the API spec for the new ItemsSourceView.IndexOf function.

See microsoft/microsoft-ui-xaml#1828 for more context.

Copy link
Contributor

@MikeHillberg MikeHillberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great -- I suggested some edits and added a couple of comments.

@marcelwgn
Copy link
Contributor Author

So during testing of the existing internal IndexOf, we noticed one problem: Having a collection consisting only pass by value types such as integers, IndexOf does not work if we pass the collection as IIterable.

See following example:

var itemSourceView = new ItemsSourceView(Enumerable.Rang(0,10));

// The following is false!
// IndexOf(1) returns -1 
Assert.AreEqual(1,itemSourceView.IndexOf(1));

When passing pass by value types, they get boxed as objects. This happens both when creating an ItemsSourceView and when we call IndexOf. However those boxed objects will not be the same, so finding pass by value types using IndexOf fails.

The big question: Should we support it, or just point out in the documentation that this won't work?
Pass by value types are not a common scenario for ItemsSourceView, so is supporting them really necessary or beneficial?

@MikeHillberg
Copy link
Contributor

Good point. This case is actually handled in the analogous ItemCollection.IndexOf, and similarly by Selector.SelectedItem, by unboxing and checking for the fundamental value types and for interfaces.

I don't know if there's any public API that exposes that functionality though. Does TabView.SelectedItem have code for it?

@marcelwgn
Copy link
Contributor Author

Since the TabView uses a ListView internally, we do whatever ListView does to keep this up to date.

The main problem I see with doing this manually, is that we would have to unbox all the time, pushing down performance. Since the ItemsRepeater that uses this class, is mainly designed for large collections, this could really make a significant difference. And since most of the time, people actually pass objects and not primitive types, I am not sure if it's worth dropping performance for this "corner case".

If somebody wants to use IndexOf with pass by value types, they could use a different collection. We only would have a say in this if we get passed an IIterable, in other cases we don't even have an option on what we do, we just pass arguments down. So we might just say:

Pass by value types are not supported, if you want to use them use ... as itemssource.

@ranjeshj
Copy link

Since the TabView uses a ListView internally, we do whatever ListView does to keep this up to date.

The main problem I see with doing this manually, is that we would have to unbox all the time, pushing down performance. Since the ItemsRepeater that uses this class, is mainly designed for large collections, this could really make a significant difference. And since most of the time, people actually pass objects and not primitive types, I am not sure if it's worth dropping performance for this "corner case".

If somebody wants to use IndexOf with pass by value types, they could use a different collection. We only would have a say in this if we get passed an IIterable, in other cases we don't even have an option on what we do, we just pass arguments down. So we might just say:

Pass by value types are not supported, if you want to use them use ... as itemssource.

Right. It is quite common for someone to 'try' an enumerable of integers, however in most cases, the collection is going to be a non-value type. we still have the out of saying, if you want to use its, use a collection of some sort (like observablecollection) and In that case we will delegate to the collection. I agree that we should not be doing extra work for this case that might impact perf. I have not checked, but ListView likely has the same issue...

@MikeHillberg
Copy link
Contributor

ListView likely has the same issue

ListView actually works, both SelectedItem and Items.IndexOf. The other case boxing shows up is in a list of structs, like a List<Point>. This will be easier with WinUI3 where we could share the code that ListView uses more easily. Maybe doc it until then.

@marcelwgn
Copy link
Contributor Author

ListView actually works, both SelectedItem and Items.IndexOf. The other case boxing shows up is in a list of structs, like a List. This will be easier with WinUI3 where we could share the code that ListView uses more easily. Maybe doc it until then.

I've updated the spec to point out how pass by value types behave and how one can use them.

@ranjeshj
Copy link

ListView actually works, both SelectedItem and Items.IndexOf. The other case boxing shows up is in a list of structs, like a List. This will be easier with WinUI3 where we could share the code that ListView uses more easily. Maybe doc it until then.

I've updated the spec to point out how pass by value types behave and how one can use them.

I did not realize that ListView was working. I think we should make it work here also. I am ok with creating an issue and following up on that since it does not affect the API surface. I can see structs being used in this scenario where this can be a problem.

@marcelwgn
Copy link
Contributor Author

ListView actually works, both SelectedItem and Items.IndexOf. The other case boxing shows up is in a list of structs, like a List. This will be easier with WinUI3 where we could share the code that ListView uses more easily. Maybe doc it until then.

I've updated the spec to point out how pass by value types behave and how one can use them.

I did not realize that ListView was working. I think we should make it work here also. I am ok with creating an issue and following up on that since it does not affect the API surface. I can see structs being used in this scenario where this can be a problem.

So should we support pass by value in the ItemsSourceView then? In that case, I think I could also fix this with the PR that we already have in WinUI that would add that API.

@ranjeshj
Copy link

ListView actually works, both SelectedItem and Items.IndexOf. The other case boxing shows up is in a list of structs, like a List. This will be easier with WinUI3 where we could share the code that ListView uses more easily. Maybe doc it until then.

I've updated the spec to point out how pass by value types behave and how one can use them.

I did not realize that ListView was working. I think we should make it work here also. I am ok with creating an issue and following up on that since it does not affect the API surface. I can see structs being used in this scenario where this can be a problem.

So should we support pass by value in the ItemsSourceView then? In that case, I think I could also fix this with the PR that we already have in WinUI that would add that API.

Let's follow up with a separate PR for that specific change. We could possibly share some of this code in WinUI3. Thanks.

@marcelwgn
Copy link
Contributor Author

So is this spec then fine as it currently is or should I revert my last commit adding a comment regarding pass by value?

marcelwgn and others added 2 commits April 2, 2020 12:51
Copy link
Contributor

@MikeHillberg MikeHillberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @chingucoding!

@MikeHillberg MikeHillberg merged commit ab487ea into microsoft:master Apr 4, 2020
@marcelwgn marcelwgn deleted the itemssource-view-indexof-api branch April 4, 2020 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants