-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Skip null-element check for collections with a value-type element type #5432
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
Conversation
build.psm1
Outdated
| $ReleaseVersion = $ReleaseTagToUse | ||
| } else { | ||
| $ReleaseVersion = (Get-PSCommitId) -replace '^v' | ||
| $ReleaseVersion = (Get-PSCommitId -WarningAction SilentlyContinue) -replace '^v' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change does not seem related to this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I will revert it.
| $expected = $baseline + 20 | ||
|
|
||
| if ($IsWindows) { | ||
| $null = New-Item -Path $TESTDRIVE/file1 -ItemType File |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-ItemType File is not necessary anymore. The default itemtype is file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I will remove it.
| param( | ||
| [ValidateNotNullOrEmpty()] | ||
| $Value, | ||
| [string] $TestType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a parameter like: [System.Nullable``1[[System.Int32]]] $nullableInt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A [System.Nullable[int]] parameter is not useful in this case because the type is not a collection. Hence ValidateNotNullOrEmpty attribute won't validate it as a collection.
iSazonov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave a comment
| isEmpty = false; | ||
| // If the element of the collection is of value type, then no need to check for null | ||
| // because a value-type value cannot be null. | ||
| if (isElementValueType) { break; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems we can move this before while line 1997 - we check first element in ParameterCollectionTypeInformation in IsArgumentCollection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't check the elements of arguments in IsArgumentCollection. The argument passed in is the type of arguments, not arguments itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I see that no element check is in ParameterCollectionTypeInformation.
But the code is not clear. Maybe:
# Check if the collection is empty.
if (ienum.MoveNext()) isEmpty = false;
# Check every element in the collection only if the element type of the collection is NOT a value type.
if (!isElementValueType && !isEmpty)
{
do
{
...
object element = ienum.Current;
...
} while(ienum.MoveNext()))
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the logic is clear -- if the element type of the collection is a value type, then skip checking each element. The isEmpty check is needed in either case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic is right but the code is slightly tricky for me. I added your comments in my sample above. Also we do two actions that can be carried before the cycle - if we are thinking about performance it is important - I think Measure-Object show a delay starting with 10000 elements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get your point. I will update as you suggested. Thanks!
| } | ||
| } | ||
| else if ((ienum = arguments as IEnumerable) != null) | ||
| else if (IsArgumentCollection(arguments.GetType(), out bool isElementValueType)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is in the context isEmpty = !isElementValueType ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the check of element type doesn't involve inspecting the elements of the collection. You can see that the type of arguments is passed in instead of the arguments itself.
Please see the constructor of ParameterCollectionTypeInformation for details.
| isEmpty = false; | ||
| // If the element of the collection is of value type, then no need to check for null | ||
| // because a value-type value cannot be null. | ||
| if (isElementValueType) { break; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why if we calculate this before the cycle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same reason as above. The element type is resolved using the collection type.
|
@iSazonov You comments have been addressed. Please take another look when you have time. Thanks! |
iSazonov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with two minor comments.
| Context "ValidateNotNull, ValidateNotNullOrEmpty and Not-Null-Or-Empty check for Mandatory parameter" { | ||
|
|
||
| BeforeAll { | ||
| function MandType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please use more nice name? MandatoryType?
| #region NULL validation attributes | ||
|
|
||
| /// <summary> | ||
| /// Base type of Null Validation attributes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please add final dot in public comments?
|
@PowerShell/powershell-committee reviewed this and approves with this change |
|
@daxian-dbw restarted AppVeyor build. Failed due to #5567 |
PowerShell#5432) * Fix NotNullOrEmpty check logic * Fix a test issue on Unix
#5432) * Fix NotNullOrEmpty check logic * Fix a test issue on Unix
Fix #5417
Mandatoryparameter,ValidateNotNullandValidateNotNullOrEmptyattributes, skip null-element check if the collection's element type is value type.ValidateNotNullandValidateNotNullOrEmpty, they are changed to do null/empty check only on collections (as defined inParameterCollectionTypeInformation) and hashtable. They currently enumerate elements of any object that implementsIEnumerableand also enumerate elements if the argument is an enumerator. I think this behavior is not right for the following reasons:ValidateNotNull/ValidateNotNullOrEmptyattributes wait on that.GetEnumerator()method is not supported in .NET Core on COM object. (See the COM example below)COM Example
Enumerator Example