Click here to Skip to main content
15,891,689 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
i am reading a OPC client source code.
some syntax i don't understand.

Opc.Da.Subscription group;

          var item = server.CreateSubscription(groupState);   //item is a Interface
          group = (Subscription)item;


syntax like this : object= (class)Interface
does it mean Casting a Interface(item) to a Class?

What I have tried:

group = item;

it return error:
Quote:
CS0266 Cannot implicitly convert type 'Opc.Da.ISubscription' to 'Opc.Da.Subscription'. An explicit conversion exists (are you missing a cast?)


That why I guess it means Casting Interface to Class.
but what does it means actually?
thanks
Posted
Updated 12-Oct-17 23:55pm

Assuming Subscription implements ISubscription, there is an explicit cast:
C#
Subscription sub = (Subscription) iSub;
But you can't do it implicitly like this:
C#
Subscription sub = iSub;
Why not? Well ... it's explicitly forbidden!
If you look here: (it's retired documentation, so you'll have to download the PDF)

It says:
Quote:
User-defined conversions are not allowed to convert from or to interface-types. In particular, this restriction ensures that no user-defined transformations occur when converting to an interface-type, and that a conversion to an interface-type succeeds only if the object being converted actually implements the specified interface-type.
Which means you cannot define an implicit conversion from an interface to a concrete type.
 
Share this answer
 
Comments
Member 13462842 13-Oct-17 4:33am    
Would you help to guess the use of "cast iSub to Sub" ?

As Subscription implements iSub, why not just instantiate Subscription?
OriginalGriff 13-Oct-17 4:46am    
Because you will get a new instance.
You can't instantiate an interface: only the concrete class derived from it (makes sense when you think about it, just like you can't live in a tenancy agreement, but you need a tenancy agreement to rent the house - the house is concrete, the agreement is an interface).
So when you use a variable of Interface type, it always contains a derived class instance - but which one? Could be thousands...

Gotta go, the cat has just let a live mouse loose in my computer room...
Member 13462842 13-Oct-17 5:23am    
sorry, still confused. Assuming Subscription implements ISubscription.
a)Subscription sub = (Subscription) iSub;
b)subscription sub = new Subscription();

is sub in a) an Instance of Subscription?
are sub in a) and b) different?

thank you!
OriginalGriff 13-Oct-17 5:41am    
a) Maybe. If iSub contains an instance of Subscription (or a class derived from Subscription) then yes. If it contains a unrelated class instance then you will get a run time error.
public class Subscription : ISubscription {...}
public class NotASubscription : ISubscription {...}
...
ISubscription s = new Subscription();
Subscription sub = (Subscription) s;  // Works.
s = new NotASubscription();
sub = (Subscription) s;               // Compiles, but throws an InvalidCastException


Are a and b the same? No. b creates a new instance of the class, which is not related to the existing one. Think about it this way:
You have a car. It is an instance of the class Car, just as mine is: but there are not the same instance: yours is a red Ferrari, mine is a black Mercedes.
But you always refer the vehicle as "my car" - you have a variable which "points out" which vehicle is the one you own. If you put your phone in teh glove box of your car:
myCar.GloveBox.Add(myPhone)

and then change to a new Lamborghini:
myCar = new Lamborghini();

Would you expect myCar.GloveBox to still contain your phone?
Richard Deeming 13-Oct-17 9:25am    
There's an updated link for the C# language specification on the new "docs" site:
C# 6.0 draft Language Specification[^]

I can't find the exact section you've quoted, but the "conversions" topic seems to cover it:

Conversions | User-defined conversions[^]
Classes | Conversion operators[^]

A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:
...
Neither S nor T is an interface_type.
Your difficulty in understanding is probably because of your specific example. You have Subscription and ISubscription and there is a one-to-one relationship there and you can really use either of them interchangeably. If you look at a more general example of interfaces you'll gain a better understanding. The difference between Subscription and ISubscription is that Subscription can only reference the concrete class Subcription, however ISubscription can reference *any* concrete class that implements ISubscription. In your example there is only one such class, Subscription, so it's harder to understand the difference between interfaces and classes.

The example below uses an IAnimal interface and two concrete classes of Cat and Dog that both implement this interface.

static Cat GetCatObject()
{
    return new Cat();
}

static IAnimal GetCatByInterface()
{
    return new Cat();
}

static Dog GetDogObject()
{
    return new Dog();
}

static IAnimal GetDogByInterface()
{
    return new Dog();
}

static void Main(string[] args)
{
    IAnimal catA = GetCatByInterface();
            
    // catA is IAnimal so it can point to any object that implements IAnimal
    // GetCatByInterface returns Cat so the code above is valid however catA
    // can point to anything that is IAnimal so the line below is also valid

    catA = GetDogByInterface();

    // so something of type IAnimal can reference anything IAnimal

    // now we'll use concrete classes rather than interfaces

    Cat catC = GetCatObject();

    // the code above is fairly obvious, catC is Cat and GetCatObject returns Cat

    Cat catD = (Cat)GetCatByInterface();

    // catD can only point to an object that is Cat, however GetCatByInterface can return
    // anything that implements IAnimal, and that includes Dog, there is no guarantee it returns Cat.
    // The calling code doesn't know what concrete object GetCatByInterface returns, only that it is IAnimal.
    // So we have to cast whatever comes back to Cat.  Now look at the line below

    Cat catE = (Cat)GetDogByInterface();

    // this code compiles because the calling code still doesn't know what GetDogByInterface
    // returns.  We know it returns IAnimal so it could return Cat, Dog, Chicken, however
    // when the code runs it will throw an exception as the object that GetDogByInterface
    // returns can't be cast to Cat.

    Console.ReadLine();
}
 
Share this answer
 
Comments
Member 13462842 13-Oct-17 11:06am    
Cat catE = (Cat)GetDogByInterface();
//if i want a Cat, why would i call GetDogbyInterface()?
when i know it will throw an exception anyway.

thank you!
F-ES Sitecore 13-Oct-17 11:17am    
You know it returns a dog because of the name I gave it. Let's say I'm following up a dog procedure have a patient ID who has a dog and I want the instance of that patient's dog.

Dog dog = (Dog)GetPatientPet(123);

now let's say I'm following up a cat's procedure for a different patient

Cat cat = (Cat)GetPatientPet(456);

Code like this *is* dangerous as we know that GetPatientPet can return any IAnimal and we are making an assumption that patient 123 will return Dog and 456 Cat. In reality you'd use things like the "as" keyword rather than casting

Cat cat = GetPatientPet(456) as Cat;

now if patient 456 has a dog and not a cat then cat is null rather than it throwing an exception.
Member 13462842 13-Oct-17 11:29am    
code like this is dangerous. do you mean avoid code like this?
what would you suggest?
F-ES Sitecore 13-Oct-17 11:35am    
It's dangerous as you're making assumptions about the concrete class being returned. The dangerous bit is the cast, so as suggested you should use "as" instead as that returns null if the cast is invalid rather than throwing an exception.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900