Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot implicitly convert type 'customtype' to 'othercustomtype'

I am new to C#. I have a Persons class and a User class which inherits from the Persons class. I my console I input a users in an array. Then I can add a note to a user that is in the users array by only entering the users id. In my Persons class i have this function that has to search if this user is in the users array.

public static Persons FindPerson(Persons[] persons, int noteid)
{
    foreach (Persons person in persons)
        if (person.ID == noteid) return person;
    return null;
}

In my User class I have a function that loops the whole input of the id until it gets an id that is in the users array.

public static User SelectUser(User[] users)
{
    while (true)
    {
        Console.Write("Please enter the User id: ");
        string input = Console.ReadLine();
        int id;
        if (int.TryParse(input, out id))
        {
            Persons person = Persons.FindPerson(users, id);
            if (person != null) return person; // fail on "return person"                   
        }
        Console.WriteLine("The User does not exist. Please try again.");                
    }
}

Everything works fine except that I now get this error message on the "return person" in the if statement.

Cannot implicitly convert type 'UserCustomerNotes.Persons' to 'UserCustomerNotes.User'. An explicit conversion exists (are you missing a cast?)

Can anyone please help? Thanks in advance.

like image 534
CSharpSuzie Avatar asked Sep 21 '10 06:09

CSharpSuzie


Video Answer


3 Answers

Because a Person is not nessecarily a User, the compiler is not able to implicitly convert a Person to a User. In your particular case, since you know you have a list of Users, you can explicitly tell it, "I know this Person is actually a User" with the following:

if (person != null)
   return (User) person;

The cast ((User)) will throw an exception at runtime if the instance is not actually a User, but since you've started with a collection of Users to begin with, you don't need to worry.

like image 175
Dean Harding Avatar answered Oct 17 '22 09:10

Dean Harding


You should rewrite the return snippet like so:

User user = Persons.FindPerson(users, id) as User;
if (user != null) return user;

The problem you were having was to do with you trying to return a base class from a method that should return a more derived class. The compiler cannot automatically downcast(Persons->User), but it can upcast (User->Persons)

like image 4
Igor Zevaka Avatar answered Oct 17 '22 09:10

Igor Zevaka


Since User inherits from Person, you cannot implicitly convert any random Person to a User (though you can implicitly convert a User to a Person).

Since you pass a User[] to FindPerson(users, id), you can be sure the returned person is indeed a User, so you can cast it like this:

return (User)person;

Edit: You might consider using generics on FindPerson to avoid the cast altogether.

public static T FindPerson<T>(IEnumerable<T> persons, int noteid)
    where T : Person
{
    foreach (T person in persons)
    {
        if (person.ID == noteid)
        {
            return person;
        }
    }

    return null;
}

public static User SelectUser(User[] users)
{
    while (true)
    {
        Console.Write("Please enter the User id: ");
        string input = Console.ReadLine();
        int id;
        if (int.TryParse(input, out id))
        {
            User person = Persons.FindPerson(users, id);
            if (person != null)
            {
                return person;
            }            
        }

        Console.WriteLine("The User does not exist. Please try again.");                
    }
}
like image 4
Zach Johnson Avatar answered Oct 17 '22 11:10

Zach Johnson