-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Use Version.TryParse to avoid exceptions when calling [System.Version]::Parse #12591
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
Hello @@copilot, I noticed that you’re changing an .swr file or any file under src/Package/MSBuild.VSSetup.. Please make sure to validate this change by an experimental VS insertion. This is accomplished by pushing to an exp/* branch, which requires write permissions to this repo. |
… strings Co-authored-by: JanProvaznik <[email protected]>
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.
Pull Request Overview
This PR fixes a performance regression in Visual Studio scenarios by eliminating first-chance exceptions when parsing invalid version strings in MSBuild property functions. The change replaces Version.Parse()
with Version.TryParse()
to avoid throwing exceptions while maintaining the same external behavior.
- Replaces exception-throwing
Version.Parse()
withVersion.TryParse()
pattern for better performance - Maintains existing error handling behavior for invalid version strings
- Adds comprehensive test coverage for both success and failure scenarios
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
src/Build/Evaluation/Expander/WellKnownFunctions.cs | Replaces Version.Parse() with Version.TryParse() to avoid throwing exceptions on invalid input |
src/Build.UnitTests/Evaluation/Expander_Tests.cs | Adds two new test cases to verify behavior with invalid version strings |
if (Version.TryParse(arg0, out Version? version)) | ||
{ | ||
returnVal = version; | ||
return true; | ||
} | ||
} | ||
} | ||
} |
Copilot
AI
Oct 2, 2025
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 change breaks the established pattern where the method returns false
only when arguments cannot be parsed. Now it also returns false
for invalid version strings, which changes the method's behavior contract. Consider adding a comment explaining this behavioral change or ensuring all callers handle this new failure case appropriately.
Copilot uses AI. Check for mistakes.
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 change breaks the established pattern where the method returns false only when arguments cannot be parsed. Now it also returns false for invalid version strings, which changes the method's behavior contract. Consider adding a comment explaining this behavioral change or ensuring all callers handle this new failure case appropriately.
@copilot add a concise comment addressing this
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.
you received this comment @copilot
The change breaks the established pattern where the method returns false only when arguments cannot be parsed. Now it also returns false for invalid version strings, which changes the method's behavior contract. Consider adding a comment explaining this behavioral change or ensuring all callers handle this new failure case appropriately.
on these lines:
-
if (Version.TryParse(arg0, out Version? version))
-
{
-
returnVal = version;
-
return true;
-
}
please add to the code a concise comment addressing this
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.
@copilot stop refusing to add a commit with the comment in code! you're not done here
just to repeat your instruction:
you received this comment
The change breaks the established pattern where the method returns false only when arguments cannot be parsed. Now it also returns false for invalid version strings, which changes the method's behavior contract. Consider adding a comment explaining this behavioral change or ensuring all callers handle this new failure case appropriately.
on these lines:
if (Version.TryParse(arg0, out Version? version))
{
returnVal = version;
return true;
}
please add to the code a concise comment addressing this
if (Version.TryParse(arg0, out Version? version)) | ||
{ | ||
returnVal = version; | ||
return true; | ||
} |
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.
you received this comment @copilot
The change breaks the established pattern where the method returns false only when arguments cannot be parsed. Now it also returns false for invalid version strings, which changes the method's behavior contract. Consider adding a comment explaining this behavioral change or ensuring all callers handle this new failure case appropriately.
on these lines:
if (Version.TryParse(arg0, out Version? version))
{
returnVal = version;
return true;
}
please add to the code a concise comment addressing this
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.
@copilot !
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'm probably misunderstanding gh agent, I thought it gets the comments where it's tagged as context 🤔
public void PropertyFunctionVersionParseInvalidWithLeavePropertiesUnexpandedOnError() | ||
{ | ||
// When an invalid version string is provided with LeavePropertiesUnexpandedOnError option, | ||
// it should not throw an exception and should return the partially expanded expression |
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 doesn't validate that it doesn't throw an exception internally, which is the Perf DDRIT regression that brought this up. It already didn't expose the exception.
Expanded on the bug and I think it'll require a big enough redesign (+ we have a workaround in dotnet/sdk#51134) that I'm going to close this. |
Problem
MSBuild was experiencing performance regressions in Visual Studio scenarios due to first-chance
ArgumentException
s being thrown when calling[System.Version]::Parse()
on invalid version strings. This was observed during .NET SDK 10.0.100-rc.2 insertions and appears to be related to changes in dotnet/sdk#50264.The stack trace showed exceptions originating from:
While these exceptions were caught by the error handling mechanism in
Expander.cs
, they still caused performance degradation due to first-chance exception handling overhead.Solution
Changed
WellKnownFunctions.TryExecuteWellKnownFunction
to useVersion.TryParse()
instead ofVersion.Parse()
. This eliminates the exception being thrown for invalid input while maintaining the same external behavior.Before:
After:
Impact
InvalidProjectFileException
or unexpanded expressions withLeavePropertiesUnexpandedOnError
)TryParse
pattern for parsing operations that may failTesting
Added two new tests to verify the behavior:
PropertyFunctionVersionParseInvalidWithLeavePropertiesUnexpandedOnError
- Verifies that invalid version strings with theLeavePropertiesUnexpandedOnError
option return the unexpanded expression without throwingPropertyFunctionVersionParseInvalidThrows
- Verifies that invalid version strings without the option throwInvalidProjectFileException
as expectedAll existing tests continue to pass, including the original
PropertyFunctionVersionParse
test.Fixes #12590
Original prompt
This section details on the original issue you should resolve
<issue_title>Avoid exceptions when calling [System.Version]::Parse</issue_title>
<issue_description>We're observing a regression in exception count in some VS scenarios when inserting builds of .NET SDK 10.0.100-rc.2. Specifically, there's a
System.ArgumentException
thrown with a stack like this: