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

Replace all non-test uses of new T[0] with Array.Empty<T> #2344

Merged
merged 1 commit into from Jul 16, 2015

Conversation

Projects
None yet
@jamesqo
Contributor

jamesqo commented Jul 13, 2015

I ran a little shell command to find and replace most of the occurrences of new T[0] in the repo:

cd corefx
grep -rl "new [^ (]*\[0\]" . | grep -vi test | xargs start notepad++

There were about 18 matches, with an additional match I spotted in Queue<T>.ToArray.

Additional notes:

  • Removed caching of EmptySequence in XElement and XAttribute; this is already done by Array.Empty.
  • The build should fail at first because I forgot to add using statements to the classes I changed. Will fix once the compiler tells where it can't recognize Array.
@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 13, 2015

Member

@khdang, pelase take a look at the XmlSerializer changes to confirm whether they're acceptable or not.

@bartonjs, please take a look at the crypto changes to confirm whether they're acceptable or whether the behavioral impact (object identity of the returned object) is problematic.

@VSadov, please take a look at the dynamic, LINQ, etc. stuff.

Member

stephentoub commented Jul 13, 2015

@khdang, pelase take a look at the XmlSerializer changes to confirm whether they're acceptable or not.

@bartonjs, please take a look at the crypto changes to confirm whether they're acceptable or whether the behavioral impact (object identity of the returned object) is problematic.

@VSadov, please take a look at the dynamic, LINQ, etc. stuff.

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 13, 2015

Member

Will fix once the compiler tells where it can't recognize Array

I'm curious, does this mean you're not building locally before submitting?

Member

stephentoub commented Jul 13, 2015

Will fix once the compiler tells where it can't recognize Array

I'm curious, does this mean you're not building locally before submitting?

@bartonjs

This comment has been minimized.

Show comment
Hide comment
@bartonjs

bartonjs Jul 13, 2015

Member

I can't imagine anyone needing reference uniqueness from the affected crypto code, so I'm good with the crypto part of the change.

Member

bartonjs commented Jul 13, 2015

I can't imagine anyone needing reference uniqueness from the affected crypto code, so I'm good with the crypto part of the change.

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 13, 2015

Member

Great; thanks, Jeremy.

Member

stephentoub commented Jul 13, 2015

Great; thanks, Jeremy.

@khdang

This comment has been minimized.

Show comment
Hide comment
@khdang

khdang Jul 13, 2015

Member

The changes in XmlSerializer look good to me.

Member

khdang commented Jul 13, 2015

The changes in XmlSerializer look good to me.

@JonHanna

This comment has been minimized.

Show comment
Hide comment
@JonHanna

JonHanna Jul 13, 2015

Collaborator

I can see a reverse danger to this; someone could come to expect that the result of some of these operations are all the same object and then be surprised down the line (or perhaps upon deserialisation if they hadn't previously considered this).

I don't see that being a big issue (I can remember people being confused by the fact that ReferenceEquals(string.Empty, "") changed between framework versions, but not stymied by it). But better to consider it and rule it out as a problem than not consider it.

Collaborator

JonHanna commented Jul 13, 2015

I can see a reverse danger to this; someone could come to expect that the result of some of these operations are all the same object and then be surprised down the line (or perhaps upon deserialisation if they hadn't previously considered this).

I don't see that being a big issue (I can remember people being confused by the fact that ReferenceEquals(string.Empty, "") changed between framework versions, but not stymied by it). But better to consider it and rule it out as a problem than not consider it.

@VSadov

This comment has been minimized.

Show comment
Hide comment
@VSadov

VSadov Jul 13, 2015

Member

LINQ/Dynamic look ok except for ToArray() and where Stephen has already commented about ref comparisons.

The ToArray ones share the same concern that benefits might not be that great while user might expect new instances and therefore we were reluctant to change these. I wonder what would be the right forum to discuss the ToArray issue in general and to conclude one way or another, possibly in the context of the whole framework so it would be consistent.

Member

VSadov commented Jul 13, 2015

LINQ/Dynamic look ok except for ToArray() and where Stephen has already commented about ref comparisons.

The ToArray ones share the same concern that benefits might not be that great while user might expect new instances and therefore we were reluctant to change these. I wonder what would be the right forum to discuss the ToArray issue in general and to conclude one way or another, possibly in the context of the whole framework so it would be consistent.

@jamesqo

This comment has been minimized.

Show comment
Hide comment
@jamesqo

jamesqo Jul 14, 2015

Contributor

@Hackcraft Hm. I'm assuming you mean scenarios like this:

if (queue.ToArray() == Array.Empty<T>())
{
    // ...

That might happen if someone did stumbled on this by chance and assumed that it would always be true, but in general I think most people would go for checking the length of the array or some variant.

That said, I am undoing the changes I made to Queue for now.

Contributor

jamesqo commented Jul 14, 2015

@Hackcraft Hm. I'm assuming you mean scenarios like this:

if (queue.ToArray() == Array.Empty<T>())
{
    // ...

That might happen if someone did stumbled on this by chance and assumed that it would always be true, but in general I think most people would go for checking the length of the array or some variant.

That said, I am undoing the changes I made to Queue for now.

@krwq

This comment has been minimized.

Show comment
Hide comment
@krwq

krwq Jul 14, 2015

Member

Not sure if I remember correctly: I believe we used to have Array.Empty internally some time ago for a while and then we reverted the changes as Array.Empty is not available on some earlier versions of full .NET and we wanted to be compatible with as many versions as possible.

We should find out who did the internal revert to figure out if we should re-do it.

Member

krwq commented Jul 14, 2015

Not sure if I remember correctly: I believe we used to have Array.Empty internally some time ago for a while and then we reverted the changes as Array.Empty is not available on some earlier versions of full .NET and we wanted to be compatible with as many versions as possible.

We should find out who did the internal revert to figure out if we should re-do it.

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 14, 2015

Member

@krwq, can you do that? Thanks.

Member

stephentoub commented Jul 14, 2015

@krwq, can you do that? Thanks.

return arr;
return arr; // consider replacing with Array.Empty<T>() to be consistent with non-generic Queue

This comment has been minimized.

@stephentoub

stephentoub Jul 14, 2015

Member

Hmm, it looks like I'm being inconsistent with myself. I'd previously changed Queue.ToArray to return Array.Empty<object>, doing so for the other NonGeneric collections as well, but I explicitly avoided doing so for the generic ones. I don't remember now what my rationale was for thinking it was ok to convert one set but not the other. Seems like (separate from this PR), we should reevaluate that; I'm tempted to roll back those changes to the non-generic collections, as they exist primarily for backwards compatibility, and any code more sensitive to performance should be using the generic ones, especially with value types.

@stephentoub

stephentoub Jul 14, 2015

Member

Hmm, it looks like I'm being inconsistent with myself. I'd previously changed Queue.ToArray to return Array.Empty<object>, doing so for the other NonGeneric collections as well, but I explicitly avoided doing so for the generic ones. I don't remember now what my rationale was for thinking it was ok to convert one set but not the other. Seems like (separate from this PR), we should reevaluate that; I'm tempted to roll back those changes to the non-generic collections, as they exist primarily for backwards compatibility, and any code more sensitive to performance should be using the generic ones, especially with value types.

@krwq

This comment has been minimized.

Show comment
Hide comment
@krwq

krwq Jul 14, 2015

Member

XML parth looks good to me 👍 Also please disregard my previous comment.

Member

krwq commented Jul 14, 2015

XML parth looks good to me 👍 Also please disregard my previous comment.

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 15, 2015

Member

Thanks, @James-Ko. Looks good. Can you please squash this?

Member

stephentoub commented Jul 15, 2015

Thanks, @James-Ko. Looks good. Can you please squash this?

@jamesqo

This comment has been minimized.

Show comment
Hide comment
@jamesqo

jamesqo Jul 15, 2015

Contributor

I have no idea why, but it seems that the build is suddenly failing after I squashed the commits. According to Jenkins, it seems to be a problem with EtwTests on Linux, which I have not heard of nor touched. I'm going to try a soft reset to the last commit and re-push.

Contributor

jamesqo commented Jul 15, 2015

I have no idea why, but it seems that the build is suddenly failing after I squashed the commits. According to Jenkins, it seems to be a problem with EtwTests on Linux, which I have not heard of nor touched. I'm going to try a soft reset to the last commit and re-push.

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 15, 2015

Member

@James-Ko, I don't believe this is related to your PR. Others are failing with the same issue. I'm suspecting that there's either something wrong with the infrastructure or that something's changed with the CoreCLR we're pulling in. @mmitche, @ellismg, ideas?

Member

stephentoub commented Jul 15, 2015

@James-Ko, I don't believe this is related to your PR. Others are failing with the same issue. I'm suspecting that there's either something wrong with the infrastructure or that something's changed with the CoreCLR we're pulling in. @mmitche, @ellismg, ideas?

@mmitche

This comment has been minimized.

Show comment
Hide comment
@mmitche

mmitche Jul 16, 2015

Member

This looks like maybe a change got merged in that accidentally enabled etw tests on Linux? It doesn't makes sense to run them there anyway.

Member

mmitche commented Jul 16, 2015

This looks like maybe a change got merged in that accidentally enabled etw tests on Linux? It doesn't makes sense to run them there anyway.

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 16, 2015

Member

it doesn't makes sense to run them there anyway.

It does, actually. These have been running on Linux for a long time. EventSource works on Linux, it just isn't hooked up to ETW. EventListeners still receive events, and these tests make sure those events are raised.

Member

stephentoub commented Jul 16, 2015

it doesn't makes sense to run them there anyway.

It does, actually. These have been running on Linux for a long time. EventSource works on Linux, it just isn't hooked up to ETW. EventListeners still receive events, and these tests make sure those events are raised.

@ellismg

This comment has been minimized.

Show comment
Hide comment
@ellismg

ellismg Jul 16, 2015

Contributor

Still trying to dig into this but I have to run for a bit so it won't happen until later tonight.

Contributor

ellismg commented Jul 16, 2015

Still trying to dig into this but I have to run for a bit so it won't happen until later tonight.

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 16, 2015

Member

@ellismg, I'm looking as well. I have a hunch. @mmitche, you recently brought new build tools into CoreCLR, right? Is it possible that in doing so we switched something related to the $(OS) / $(OSGroup) properties and what defines get set as a result? It looks like some Windows-specific code that's protected by FEATURE_MANAGED_ETW is getting output in the Linux mscorlib now.

Member

stephentoub commented Jul 16, 2015

@ellismg, I'm looking as well. I have a hunch. @mmitche, you recently brought new build tools into CoreCLR, right? Is it possible that in doing so we switched something related to the $(OS) / $(OSGroup) properties and what defines get set as a result? It looks like some Windows-specific code that's protected by FEATURE_MANAGED_ETW is getting output in the Linux mscorlib now.

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub

stephentoub Jul 16, 2015

Member

I think this fixes it: dotnet/coreclr#1246

Member

stephentoub commented Jul 16, 2015

I think this fixes it: dotnet/coreclr#1246

@stephentoub

This comment has been minimized.

Show comment
Hide comment
@stephentoub
Member

stephentoub commented Jul 16, 2015

LGTM

@Maxwe11

This comment has been minimized.

Show comment
Hide comment
@Maxwe11

Maxwe11 Jul 16, 2015

Contributor

@dotnet-bot test this please

Contributor

Maxwe11 commented Jul 16, 2015

@dotnet-bot test this please

stephentoub added a commit that referenced this pull request Jul 16, 2015

Merge pull request #2344 from James-Ko/patch-3
Replace all non-test uses of new T[0] with Array.Empty<T>

@stephentoub stephentoub merged commit bfe5c6a into dotnet:master Jul 16, 2015

1 check passed

default Build finished. No test results found.
Details

@jamesqo jamesqo deleted the jamesqo:patch-3 branch Jul 16, 2015

@guiomie

This comment has been minimized.

Show comment
Hide comment
@guiomie

guiomie Jul 28, 2015

Hi, I was just wondering why should it be Array.Empty as opposed to new T[0] ?

guiomie commented on 9b1ed39 Jul 28, 2015

Hi, I was just wondering why should it be Array.Empty as opposed to new T[0] ?

This comment has been minimized.

Show comment
Hide comment
@akoeplinger

akoeplinger Jul 28, 2015

Member

@guiomie it saves an extra object allocation since the instance returned by Array.Empty is cached.

Member

akoeplinger replied Jul 28, 2015

@guiomie it saves an extra object allocation since the instance returned by Array.Empty is cached.

This comment has been minimized.

Show comment
Hide comment
@guiomie

guiomie Jul 28, 2015

Ahh... Thanks for answer!

guiomie replied Jul 28, 2015

Ahh... Thanks for answer!

@karelz karelz modified the milestone: 1.0.0-rtm Dec 3, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment