Why I cannot cast an object to an interface it is implementing?
I think you should take a look at my response to this question, it explains you case Interface with generic object of the interface type
By the way I suggest you make changes to you GetIt Function like that :
public static IASet<T> GetIt<T>()
where T : IItem
{
ASet a = new ASet();
a.Collection = new HashSet<OneItem>();
a.Collection.Add(new OneItem() { Name = "one" });
a.Collection.Add(new OneItem() { Name = "two" });
//for test :
foreach (var i in a.Collection)
{
Console.WriteLine(i.Name);
}
/*Error 1 Cannot implicitly convert type 'ConsoleApplication2.Program.ASet'
* to 'ConsoleApplication2.IASet<ConsoleApplication2.IItem>'. An explicit
* conversion exists (are you missing a cast?)
*/
//return a;
/*Unable to cast object of type 'ASet' to type
* 'ConsoleApplication2.IASet`1[ConsoleApplication2.IItem]'.
*/
return (IASet<T>)a;
}
and then you need to call it like that:
IASet<OneItem> aset = GetIt<OneItem>();
foreach (IItem i in aset.Collection)
Console.WriteLine(i.Name);
if you want more details you have to explain your requirement more.
Unable to cast object to interface it implements - cast interface to another interface
If you post your question correctly, it works fine:
class Program
{
static void Main()
{
Call(new Car());
Call(new MotorBike());
}
public static void Call(IVehicles vehicle)
{
Object someIrrelevantObject = vehicle.SomeValue;
//here my change begins
IPersonalVehicles personalVehicle = (IPersonalVehicles)vehicle;
long somePersonalValue = personalVehicle.SomePersonalValue;
}
}
public interface IVehicles
{
Object SomeValue { get; }
}
public interface IPersonalVehicles
{
long SomePersonalValue { get; }
}
public class Car : IVehicles, IPersonalVehicles
{
public long SomePersonalValue => long.MinValue;
public object SomeValue => "car value";
}
public class MotorBike : IVehicles, IPersonalVehicles
{
public long SomePersonalValue => long.MaxValue;
public object SomeValue => "motorbike value";
}
Why cannot I cast my COM object to the interface it implements in C#?
So, the problem was that my DLL with IDiagnostics interface was generated from a TLB, and that TLB never got registered.
Since the DLL was imported from the TLB, RegAsm.exe refuses to register the library. So I used the regtlibv12.exe tool to register the TLB itself:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\regtlibv12.exe "$(ProjectDir)\lib\Diagnostics.tlb"
Then everything magically started to work.
Since regtlibv12 is not a supported tool, I still don't know how to do this properly.
C# - Error casting object to interface
Shared projects compile their source files directly into each project that references them.
Therefore, you have two ICrawler
interfaces, one in each assembly, which are not the same type (even though they're identical).
You're trying to cast the new instance to the copy of the interface that it doesn't implement; you can't do that.
You should use a normal Class Library, not a Shared Project.
Unable to cast 2 objects although they share same interface
You can use json for this. We do this all the time to cast DataTable into a model.
You Serialize the first model and Deserialize it into the other one.
Doing it this way, only the fields that are in common are touched.
var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
string serializedObject = JsonConvert.SerializeObject(A, deserializeSettings);
B b = JsonConvert.DeserializeObject<B>(serializedObject);
foreach loop can not cast type to the interface it implements
I solved this by adding another level of indirection. Having followed advice from @PeterDuniho, I broke apart the INotification<TMessage>
interface in to two separate interfaces. By adding the new INotificationProcessor
interface, I can change my collection of listeners from an ISubscription
to an INotificationProcessor
and then iterate over my collection of listeners as an INotificationProcessor.
public interface ISubscription
{
void Unsubscribe();
}
public interface INotification<TMessageType> : ISubscription where TMessageType : class, IMessage
{
void Register(Action<TMessageType, ISubscription> callback);
}
public interface INotificationProcessor
{
void ProcessMessage(IMessage message);
}
The INotificationProcessor
implementation, implements both INotificationProcessor
and INotification<TMessageType>
. This allows the Notification
class below to cast the IMessage provided in to the appropriate generic type for publication.
internal class Notification<TMessage> : INotificationProcessor, INotification<TMessage> where TMessage : class, IMessage
{
private Action<TMessage, ISubscription> callback;
public void Register(Action<TMessage, ISubscription> callbackMethod)
{
this.callback = callbackMethod;
}
public void Unsubscribe()
{
this.callback = null;
}
public void ProcessMessage(IMessage message)
{
// I can now cast my IMessage to T internally. This lets
// subscribers use this and not worry about handling the cast themselves.
this.callback(message as TMessage, this);
}
}
My NotificationManager
can now hold a collection of INotificationProcessor
types instead of ISubscription
and invoke the ProcessMessage(IMessage)
method regardless if what comes in to it is an IMessage
or a ServerMessage
.
public class NotificationManager
{
private ConcurrentDictionary<Type, List<INotificationProcessor>> listeners =
new ConcurrentDictionary<Type, List<INotificationProcessor>>();
public ISubscription Subscribe<TMessageType>(Action<TMessageType, ISubscription> callback) where TMessageType : class, IMessage
{
Type messageType = typeof(TMessageType);
// Create our key if it doesn't exist along with an empty collection as the value.
if (!listeners.ContainsKey(messageType))
{
listeners.TryAdd(messageType, new List<INotificationProcessor>());
}
// Add our notification to our listener collection so we can publish to it later, then return it.
var handler = new Notification<TMessageType>();
handler.Register(callback);
List<INotificationProcessor> subscribers = listeners[messageType];
lock (subscribers)
{
subscribers.Add(handler);
}
return handler;
}
public void Publish<T>(T message) where T : class, IMessage
{
Type messageType = message.GetType();
if (!listeners.ContainsKey(messageType))
{
return;
}
// Exception is thrown here due to variance issues.
foreach (INotificationProcessor handler in listeners[messageType])
{
handler.ProcessMessage(message);
}
}
}
The original app example now works without issue.
class Program
{
static void Main(string[] args)
{
var notificationManager = new NotificationManager();
ISubscription subscription = notificationManager.Subscribe<ServerMessage>(
(message, sub) => Console.WriteLine(message.Content));
notificationManager.Publish(new ServerMessage("This works"));
IMessage newMessage = MessageFactoryMethod("This works without issue.");
notificationManager.Publish(newMessage);
Console.ReadKey();
}
private static IMessage MessageFactoryMethod(string content)
{
return new ServerMessage(content);
}
}
Thanks everyone for the help.
Force cast a COM object to an interface
You can't cast an object to an interface it does not implement. So you can't create your own interface and try to cast an object to it.
You can try using dynamic
instead. You'll loose IntelliSense support, but I think you can live with this.
C# Can't cast to interface even though it inherits it
The problem you're seeing is one of co-variance.
If you have these type definitions:
public class ModelConverterList : List<IModelConverter<IDataCollection>> { }
public interface IModelConverter<in T> : IConverter where T : IDataCollection { }
public interface IDataCollection { }
public interface IConverter { }
...then with this code:
private static ModelConverterList modelConverters = new ModelConverterList();
public static void AddModelConverter<T>(IModelConverter<T> converter) where T : IDataCollection
{
modelConverters.Add(converter);
}
...you get the following error:
CS1503 Argument 1: cannot convert from 'IModelConverter<T>' to 'IModelConverter<UserQuery.IDataCollection>'
Even though we know that T
inherits from IDataCollection
, it isn't the same as saying that IModelConverter<T>
inherits from IModelConverter<IDataCollection>
- it doesn't. So there is no cast from IModelConverter<T>
to IModelConverter<IDataCollection>
.
This compiles:
public class ModelConverterList : List<IModelConverter<IDataCollection>> { }
public interface IModelConverter<out T> : IConverter where T : class, IDataCollection { }
public interface IDataCollection { }
public interface IConverter { }
private static ModelConverterList modelConverters = new ModelConverterList();
public static void AddModelConverter<T>(IModelConverter<T> converter) where T : class, IDataCollection
{
modelConverters.Add(converter);
}
But I've changed the definition of IModelConverter
from in T
to out T
and added a class
constraint.
Why can't I cast this interface to a concrete class?
The reason is that newItem
can be any type that implements IApiDataWithProperties
, so compiler can't guarantee that it's type is convertible to Event
. Even if you check it using is
operator it means nothing to the compiler. As a workaround you can use double cast:
((Event)(object)newItem).Log();
Even though this works, it doesn't mean you should use it. You shouldn't check the type in a generic method. Instead try using polymorphism, add the Log
method to IApiDataWithProperties
or some other interface and implement it in your types. Then have another constraint for that interface, then you can call the method without needing a cast.
Related Topics
How to Put Conditional Required Attribute into Class Property to Work with Web API
Expression-Bodied Function Members Efficiency and Performance in C# 6.0
Share Session Between Two Web Sites Using ASP.NET and State Server
Return Only Digits 0-9 from a String
Count Number of Mondays in a Given Date Range
How to Check If Another Instance of the Application Is Running
Webdriver How to Wait Until the Element Is Clickable in Webdriver C#
Mapping Database Views to Ef 5.0 Code First W/Migrations
Can Someone Explain How Bcrypt Verifies a Hash
Where Are the Controllercontext and Viewengines Properties in MVC 6 Controller
How to Use Datareceived Event of the Serialport Port Object in C#
File Write Permission Issue Under "Program Files" Folder
Gracefully Handling Corrupted State Exceptions
Setting Dropdownlist Selecteditem Programmatically
How to Split a Number into Individual Digits in C#
How to Print PDF on Default Network Printer Using Ghostscript (Gswin32C.Exe) Shell Command