Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit/implicit cast operator fails when using LINQ's .Cast() operator

I am trying to use a class that has a explicit (but also fails with implicit) cast operator that fails when using LINQ's Cast<T>() function. Here is the definitions of the two classes

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; } } 

Here is the code I am using to test it.

//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>()); 

Here is the exception I get

 System.InvalidCastException was unhandled by user code   HResult=-2147467262   Message=Unable to cast object of type 'Server.Config.DatabaseInfoElement' to type 'Server.DatabaseInfo'.   Source=System.Core   StackTrace:        at System.Linq.Enumerable.d__b1`1.MoveNext()        at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)        at Sandbox.Main() in E:\Code\Sandbox\Program.cs:line 82   InnerException:  

What am I doing wrong in my casting to get this to work the way I want?

like image 918
Scott Chamberlain Avatar asked Nov 09 '12 22:11

Scott Chamberlain


1 Answers

When you define explicit/implicit cast operators, they are bound at call-sites at compile-time. That's why the first line works: the compiler can work out all the type information needed, and so it can substitute your custom explicit cast operator for the default one.

However, since the Cast<T> just performs a generic cast, the compiler doesn't know about your operator, and thus it is ignored. Result: invalid cast exception.

You can get around this by instead performing a .Select(x => (DatabaseInfo)x). Alternatively, you could add on a method called ToDatabaseInfo(), so that you're not hiding what's actually going on.

like image 183
dlev Avatar answered Sep 18 '22 21:09

dlev