0
votes

I get this error message in the last line of OnPlayFabError method:

return output;

Error CS0029: Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task'

What is wrong with the line return output;? I want to get the value of the variable "output" in this line:

error = errormessage.Result;

What is wrong with my code?

MainClass.cs:

string Countryname = string.Empty;
string Cityname = string.Empty;
string Errormessage = string.Empty;
var GotNames = await Extensionmethods.GetPlayerCountryData(PlayerPlayFabID, "Country", "City");
Countryname = GotNames.countryname;
Cityname = GotNames.cityname;
Errormessage = GotNames.error;

Extensionmethods.cs:

public static class Extensionmethods
{
    public static async Task<(string error, string countryname, string cityname)> GetPlayerCountryData(this string playerplayfabid, string country, string city)
    {
        string error = string.Empty;
        string countryname = string.Empty;
        string cityname = string.Empty;

        var resultprofile = await PlayFabClientAPI.GetUserDataAsync(new PlayFab.ClientModels.GetUserDataRequest()
        {
            PlayFabId = playerplayfabid,
            Keys = null
        });

        if (resultprofile.Error != null)
        {
            // Handle error if any
            var errormessage = OnPlayFabError(resultprofile.Error);
            error = errormessage.Result;
        }
        else
        {
            if (resultprofile.Result.Data == null || !resultprofile.Result.Data.ContainsKey(country) || !resultprofile.Result.Data.ContainsKey(city))
                Console.WriteLine("No Country/City");
            else
            {
                countryname = resultprofile.Result.Data[country].Value;
                cityname = resultprofile.Result.Data[city].Value;
            }
        }

        return (error, countryname, cityname);
    }

    public static Task<string> OnPlayFabError(this PlayFabError obj)
    {
        string output = string.Empty;
        switch (obj.Error)
        {
            case PlayFabErrorCode.AccountBanned:
                output = "Account is banned." + "Hier die geladenen Daten aus der Textdatei anzeigen.";
            break;
            case PlayFabErrorCode.EmailAddressNotAvailable:
                output = "E-mail address is already in use. Please choose another e-mail address.";
            break;
            case PlayFabErrorCode.InvalidParams:
                output = "Please fill out all the text fields.";
            break;
            case PlayFabErrorCode.InvalidUsernameOrPassword:
                output = "Wrong username or password.";
            break;
            case PlayFabErrorCode.UsernameNotAvailable:
                output = "Username not available. Please choose another username.";
            break;
            case PlayFabErrorCode.ConnectionError:
                output = "Connection error. Please check your network connection.";
            break;
            default:
                output = "Unknown error!";
            break;
        }

        return output;
    }
}
2
return Task.FromResult(output); which returns completed Task with Result == output - Dmitry Bychenko
You have no Tasks in OnPlayFabError so just return string, not Task<string>. The error is telling you that a string is not Task<string>, you could return Task.FromResult(output) but that is pointless because, again, you have no Tasks to run. - Crowcoder
This is because a string is not a Task. Returning the type within the angle brackets of a task directly only works in an async method, as it does some magic to it (take a look at it under the hood). In non async methods you can either Task.FromResult it, or better yet, not return a task and mark your method as string OnPlay... and return it - MindSwipe

2 Answers

1
votes

A method returning a task should almost always be an asynchronous method. If the method isn't async, then just return the type you want, no need to wrap it in a task.

That being said, all you need to do is change the return type of your OnPlayFabErrorAsync to string OnPlayFabErrorAsync(..) instead of Task<string> OnPlayFabErrorAsync(..). So this is your new method:

public static string OnPlayFabError(this PlayFabError obj)
{
    // ...
}
-1
votes

A good rule of thumb is that if your function returns a Task, then the function name should end with Async. This then reminds you that you need to await that function.

OnPlayFabError(this PlayFabError obj) becomes OnPlayFabErrorAsync(this PlayFabError obj) which then reminds you to await it:

var errormessage = await OnPlayFabErrorAsync(resultprofile.Error);

In your case, there is no need for OnPlayFabError to be async (because it currently does no I/O), so it might be easier to just make it return a string instead of a Task<string>.