为何使用System.Action作为返回类型?附代码示例求解析
Hey there! Let's unpack your question about System.Action and why that code refactor was done—since you're new to this, I'll keep it clear and straightforward.
First: What is System.Action?
System.Action is a built-in delegate type in .NET. Think of delegates like a "container" that holds a reference to a method (or an anonymous function, like the lambda you had in the original code).
Specifically:
- It's designed for methods that don't return any value (void return type).
- The generic versions (like
Action<T1, T2>) let you define methods that take a specific number of parameters. In your case,Action<CardsTabViewModel, Templates.Button>means the method accepts two parameters: one of typeCardsTabViewModeland one of typeTemplates.Button.
Why did the developer return System.Action here?
Looking at your before/after code, the original had a long lambda function directly passed to MessagingCenter.Subscribe. The refactor moved that logic into a method (NewMethod()) that returns an Action<CardsTabViewModel, Templates.Button>. Here are the key reasons:
1. Better Readability & Cleanliness
The original code was a single dense line of nested logic. By extracting it into a named method, anyone reading the code can immediately see that NewMethod() provides the action to handle the "DeleteQuiz" message—no need to parse a huge inline lambda to understand what's happening.
2. Reusability
If another part of the app ever needs the exact same delete quiz logic, you can just call NewMethod() to get that action, instead of copying and pasting the entire lambda. This keeps your code DRY (Don't Repeat Yourself).
3. Easier Maintenance & Testing
If you need to modify the delete logic later (like adding a confirmation message tweak or logging), you only have to change the code inside NewMethod()—you won't have to dig through the MessagingCenter.Subscribe call to find the nested lambda.
Plus, this makes unit testing simpler: you can call NewMethod() to get the action, then invoke it with test parameters to verify it behaves as expected.
4. Separation of Concerns
It separates the setup of the MessagingCenter subscription from the actual business logic of deleting the quiz. The subscription line now just says "use the action from NewMethod", which is cleaner than mixing subscription setup with the delete workflow.
Your Code Side-by-Side
Before (Inline Lambda)
MessagingCenter.Subscribe<CardsTabViewModel, Templates.Button>(this, "DeleteQuiz", async (s, btn) => { var canContinue = await DisplayAlert("Delete Quiz", "Do you want to delete the results for Quiz " + (int)btn.TapCommandParam, "OK", "Cancel"); if (canContinue == false) return; App.DB.DeleteQuizHistory((int)btn.TapCommandParam); AddQuizDetails(); });
After (Extracted to System.Action-Returning Method)
MessagingCenter.Subscribe<CardsTabViewModel, Templates.Button>(this, "DeleteQuiz", NewMethod()); } private System.Action<CardsTabViewModel, Templates.Button> NewMethod() { return async (s, btn) => { var canContinue = await DisplayAlert("Delete Quiz", "Do you want to delete the results for Quiz " + (int)btn.TapCommandParam, "OK", "Cancel"); if (canContinue == false) return; App.DB.DeleteQuizHistory((int)btn.TapCommandParam); AddQuizDetails(); }; }
内容的提问来源于stack exchange,提问作者Samantha J T Star

