0

I have the following code at the top of 90% of my OnInitializedAsync() calls and it so calls for the equivilent of a TryGetUserAsync( ... out user). Is there a way to make this cleaner/tighter?

User _user;    
var tryUser = await UserManager.GetUserAsync(Principal);
if (tryUser == null)
{
    Navigation.NavigateTo(GlobalConstants.UrlLogIn, true);
    return;
}
_user = tryUser;

Part of the issue here is _user is declared as non-nullable as this is the first thing I do in OnInitializedAsync() and so I avoid all the nullable warnings when I use it. But if I could have out _user then inside the TryGetUserAsync I could call the navigation, return false and the calling code would return.

Any way to do this?

David Thielen
  • 28,723
  • 34
  • 119
  • 193
  • Wow, shows how you ask a question can really kill it - I would put this code in a base component so you write it once then it's not a problem because you rarely have to look at it – Mister Magoo Aug 21 '23 at 13:36
  • @MisterMagoo - agree on your first comment - the C# lot are definitely sharp! I was just putting together an answer, one option of which was as you suggest a base component. Another is a layout with the code. – MrC aka Shaun Curtis Aug 21 '23 at 14:02
  • @MisterMagoo Can you tell me how my wording killed the question? I know I do that a lot, but I don't understand what I'm writing that is problematic. And I would like to do better. Also, is there a good example somewhere on how to create a basic base component for my razor files. It's not just this code, there's some other common code. And all the [Inject] services that I need in every bloody razor file. TIA – David Thielen Aug 21 '23 at 16:35
  • You did nothing wrong - you asked a specific question, but unfortunately you tagged it with `C#` and the `C#` answer is no - while the more pragmatic `Blazor` answer is "no, however...." I hate that this was closed, but I guess technically it has already been answered. – Mister Magoo Aug 21 '23 at 22:08
  • As the question is closed, we can't add answers but [this repl](https://blazorrepl.telerik.com/QxOCQbcm17LLqZ4335) shows `MyComponent` inherits `MyBase` (which implicitly inherits `ComponentBase`) and so `MyBase` can be used to perform common tasks for whichever component inherits it. – Mister Magoo Aug 21 '23 at 22:19
  • @MisterMagoo First off thanks for the tag advice. That makes sense. And I prefer pragmatic answers. On the second with the example Magoo doesn't inherit from MyBase but I get the idea. I was overthinking it. Of course there can be a base .cs class. Just not a base .razor I assume. thanks – David Thielen Aug 21 '23 at 22:24
  • Ignore Magoo - that's just something I use for my repls - MyBase and MyComponent are the demo. You can have a base written in either a .cs or a .razor but by default you don't inherit any markup because that is just a method that gets overridden in the descendant class. – Mister Magoo Aug 22 '23 at 08:09

2 Answers2

2

Not possible with out parameters as async methods cannot utilize ref or out parameters.

Lucian Wischik elaborates on the reasons behind this limitation in an MSDN thread: http://social.msdn.microsoft.com/Forums/en-US/d2f48a52-e35a-4948-844d-828a1a6deb74/why-async-methods-cannot-have-ref-or-out-parameters

As for why async methods don't support out-by-reference parameters? (or ref parameters?) That's a limitation of the CLR. We chose to implement async methods in a similar way to iterator methods -- i.e. through the compiler transforming the method into a state-machine-object. The CLR has no safe way to store the address of an "out parameter" or "reference parameter" as a field of an object. The only way to have supported out-by-reference parameters would be if the async feature were done by a low-level CLR rewrite instead of a compiler-rewrite. We examined that approach, and it had a lot going for it, but it would ultimately have been so costly that it'd never have happened.

A common solution to this challenge is to return a Tuple from the async method.

Rafal Kozlowski
  • 224
  • 2
  • 2
  • [Polite] You shouldn't really reproduce someone else's answer. Just reference it in a comment - here's the original - https://stackoverflow.com/questions/18716928/how-to-write-an-async-method-with-out-parameter – MrC aka Shaun Curtis Aug 21 '23 at 13:50
0

Why not declare User as nullable?

User? _user = await UserManager.GetUserAsync(Principal);
if (_user == null)
{
    Navigation.NavigateTo(GlobalConstants.UrlLogIn, true);
    return;
}

// You shouldn't get any warnings from here onwards as the compiler already knows
// you've checked for nullability and User can't be null at this point.

string name = User.Name; // For example won't give a warning.
User user2 = _user; // No warnings too, you can assign to non-nullable version of itself and all good.
Ghasan غسان
  • 5,577
  • 4
  • 33
  • 44
  • The `_user` is a property in the class that is later used in other methods. Those other methods don't know that it's now non-null. – David Thielen Aug 21 '23 at 16:32