web-dev-qa-db-ja.com

タイプ「customtype」を「othercustomtype」に暗黙的に変換することはできません

私はC#を初めて使用します。 PersonsクラスとPersonsクラスを継承するUserクラスがあります。私のコンソールは、配列にユーザーを入力します。次に、users idを入力するだけで、users配列にあるユーザーにメモを追加できます。私のPersonsクラスには、このユーザーがusers配列にあるかどうかを検索する必要があるこの関数があります。

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

私のUserクラスには、users配列にあるIDを取得するまで、IDの入力全体をループする関数があります。

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.");                
    }
}

Ifステートメントの「returnperson」にこのエラーメッセージが表示されることを除いて、すべて正常に機能します。

タイプ「UserCustomerNotes.Persons」を「UserCustomerNotes.User」に暗黙的に変換することはできません。明示的な変換が存在します(キャストがありませんか?)

誰か助けてもらえますか?前もって感謝します。

9
CSharpSuzie

Personは必ずしもUserではないため、コンパイラーはPersonUserに暗黙的に変換することはできません。あなたの特定のケースでは、あなたはknowUsersのリストを持っているので、「このPersonは実際にはUser "次のように:

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

キャスト ((User))インスタンスが実際にはUserでない場合、実行時に例外がスローされますが、最初はUsersのコレクションから始めたので、心配する必要はありません。 。

16
Dean Harding

UserPersonを継承するため、ランダムなPersonUserに暗黙的に変換することはできません(ただし、Userを暗黙的に変換することはできます) Person)。

_User[]_をFindPerson(users, id)に渡すので、返された人が実際にUserであると確信できるので、次のようにキャストできます。

_return (User)person;
_

編集:キャストを完全に回避するために、FindPersonでジェネリックを使用することを検討してください。

_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.");                
    }
}
_
4
Zach Johnson

リターンスニペットを次のように書き直す必要があります。

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

あなたが抱えていた問題は、より派生したクラスを返すはずのメソッドから基本クラスを返そうとしたことでした。コンパイラは自動的にダウンキャストすることはできませんが(Persons-> User)、アップキャストすることはできます(User-> Persons

3
Igor Zevaka

明示的または暗黙的な演算子を実装する必要があります。

class ClassA
{
    public string Property1 { get; set; }

    public static explicit operator ClassB(ClassA classA)
    {
        return new ClassB() { Property2 = classA.Property1 };
    }
}

class ClassB
{
    public string Property2 { get; set; }
}

var a = new ClassA() {Property1 = "test"};
ClassB b = (ClassB)a;
Console.WriteLine(b.Property2); // output is "test"
3
Pranay Rana

とにかく、最初のメソッドにはLINQ拡張メソッドを使用することをお勧めします。

using System.Collections.Generic;
using System.Linq;

public static Persons FindPerson(IEnumerable<Person> persons, int id)
{
    return persons.FirstOrDefault(p => p.ID == id);
}

ずっと良く見えますよね?

0
abatishchev