Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Skip null-element check for collections with a value-type element type #5432
Conversation
daxian-dbw
added some commits
Nov 13, 2017
daxian-dbw
assigned
adityapatwardhan
Nov 13, 2017
daxian-dbw
requested review from
lzybkr,
markekraus,
adityapatwardhan and
iSazonov
Nov 13, 2017
daxian-dbw
requested review from
BrucePay and
TravisEz13
as
code owners
Nov 13, 2017
daxian-dbw
removed request for
BrucePay and
TravisEz13
Nov 13, 2017
daxian-dbw
added
the
Breaking-Change
label
Nov 13, 2017
| @@ -568,7 +568,7 @@ Fix steps: | ||
| if ($ReleaseTagToUse) { | ||
| $ReleaseVersion = $ReleaseTagToUse | ||
| } else { | ||
| - $ReleaseVersion = (Get-PSCommitId) -replace '^v' | ||
| + $ReleaseVersion = (Get-PSCommitId -WarningAction SilentlyContinue) -replace '^v' |
| + param( | ||
| + [ValidateNotNullOrEmpty()] | ||
| + $Value, | ||
| + [string] $TestType |
adityapatwardhan
Nov 13, 2017
Member
Can you add a parameter like: [System.Nullable``1[[System.Int32]]] $nullableInt
daxian-dbw
Nov 14, 2017
Member
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.
| + $expected = $baseline + 20 | ||
| + | ||
| + if ($IsWindows) { | ||
| + $null = New-Item -Path $TESTDRIVE/file1 -ItemType File |
adityapatwardhan
Nov 13, 2017
Member
-ItemType File is not necessary anymore. The default itemtype is file
| @@ -1975,12 +1990,18 @@ protected override void Validate(object arguments, EngineIntrinsics engineIntrin | ||
| Metadata.ValidateNotNullOrEmptyFailure); | ||
| } | ||
| } | ||
| - else if ((ienum = arguments as IEnumerable) != null) | ||
| + else if (IsArgumentCollection(arguments.GetType(), out bool isElementValueType)) |
daxian-dbw
Nov 14, 2017
Member
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; } |
iSazonov
Nov 14, 2017
Collaborator
It seems we can move this before while line 1997 - we check first element in ParameterCollectionTypeInformation in IsArgumentCollection.
daxian-dbw
Nov 14, 2017
Member
We don't check the elements of arguments in IsArgumentCollection. The argument passed in is the type of arguments, not arguments itself.
iSazonov
Nov 14, 2017
•
Collaborator
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()))
}
daxian-dbw
Nov 14, 2017
Member
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.
iSazonov
Nov 15, 2017
Collaborator
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.
| 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; } |
daxian-dbw
Nov 14, 2017
Member
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! |
daxian-dbw
added
the
Review - Committee
label
Nov 20, 2017
| @@ -1865,11 +1865,40 @@ public ValidateUserDriveAttribute() | ||
| #endregion | ||
| #region NULL validation attributes | ||
| + | ||
| + /// <summary> | ||
| + /// Base type of Null Validation attributes |
| + Context "ValidateNotNull, ValidateNotNullOrEmpty and Not-Null-Or-Empty check for Mandatory parameter" { | ||
| + | ||
| + BeforeAll { | ||
| + function MandType { |
SteveL-MSFT
added
Committee-Reviewed
and removed
Review - Committee
labels
Nov 29, 2017
SteveL-MSFT
added this to the 6.0.0-GA milestone
Nov 29, 2017
|
@PowerShell/powershell-committee reviewed this and approves with this change |
|
@daxian-dbw restarted AppVeyor build. Failed due to #5567 |


daxian-dbw commentedNov 13, 2017
•
Edited 1 time
-
daxian-dbw
Nov 13, 2017
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