36

Cast<T>()LINQ の関数を使用すると失敗する明示的な (ただし、暗黙的に失敗する) キャスト演算子を持つクラスを使用しようとしています。2つのクラスの定義は次のとおりです

public class DatabaseInfoElement : ConfigurationElement
{
    [ConfigurationProperty("AllowedServer", IsRequired = true)]
    public string AllowedServer { get { return (string)base["AllowedServer"]; } }

    [ConfigurationProperty("DatabaseName", IsRequired = true)]
    public string DatabaseName { get { return (string)base["DatabaseName"]; } }

    [ConfigurationProperty("SqlInstance", IsRequired = true)]
    public string SqlInstance { get { return (string)base["SqlInstance"]; } }

    public static explicit operator DatabaseInfo(DatabaseInfoElement element)
    {
        return new DatabaseInfo(element.AllowedServer, element.DatabaseName, element.SqlInstance);
    }

}

public class DatabaseInfo
{
    public DatabaseInfo(string allowedServer, string sqlInstance, string databaseName)
    {
        AllowedServer = allowedServer;
        SqlInstance = sqlInstance;
        DatabaseName = databaseName;
    }

    public string AllowedServer { get; set; }
    public string SqlInstance { get; set; }
    public string DatabaseName { get; set; }
}

ここに私がそれをテストするために使用しているコードがあります。

//Gets the ConfigurationSection that contains the collection "Databases"
var section = DatabaseInfoConfig.GetSection();

//This line works perfectly.
DatabaseInfo test = (DatabaseInfo)section.Databases[0];

//This line throws a execption
var test2 = new List<DatabaseInfo>(section.Databases.Cast<DatabaseInfo>());

ここに私が得る例外があります

System.InvalidCastException がユーザー コードによって処理されませんでした
  HResult=-2147467262
  Message=タイプ「Server.Config.DatabaseInfoElement」のオブジェクトをタイプ「Server.DatabaseInfo」にキャストできません。
  ソース=System.Core
  スタックトレース:
       System.Linq.Enumerable.d__b1`1.MoveNext() で
       System.Collections.Generic.List`1..ctor (IEnumerable`1 コレクション) で
       E:\Code\Sandbox\Program.cs:line 82 の Sandbox.Main() で
  内部例外:

これを希望どおりに機能させるために、キャスティングで何が間違っていますか?

4

1 に答える 1

55

明示的/暗黙的なキャスト演算子を定義すると、コンパイル時に呼び出しサイトにバインドされます。これが最初の行が機能する理由です。コンパイラは必要なすべての型情報を処理できるため、カスタムの明示的なキャスト演算子をデフォルトの演算子に置き換えることができます。

ただし、Cast<T>は一般的なキャストを実行するだけなので、コンパイラは演算子を認識しないため、無視されます。結果:無効なキャスト例外。

代わりにを実行することで、これを回避できます.Select(x => (DatabaseInfo)x)ToDatabaseInfo()または、実際に何が起こっているのかを隠さないように、というメソッドを追加することもできます。

于 2012-11-09T22:07:41.737 に答える