English 中文(简体)
从(same)接口中选取的两种类型
原标题:Casting between two types derived from the (same) interface
  • 时间:2012-01-13 22:26:47
  •  标签:
  • c#
  • .net

我有一个接口和两种来源。

However, I cannot do the following:

B objectB = (B) objectA

在B源自Interface1(我是各年级的名称,但现在的点数),同样是A(A类)。 我收到以下错误信息:

不能表达A类至B类。

这两种情况都源自接口,我失踪了吗?

最佳回答
  1. Types do not derive from an interface. They implement an interface.
  2. The fact that both an Elephant and a Spider are Animals doesn t mean that you can convert one to the other.
问题回答

物体可转让给祖先(直接或间接的基类),也可转让给其使用的界面,但不得转让(即来自共同祖先的另一种类型);但是,你可以宣布:

class FooObject : IObject
{
    public string Name { get; set; }
    public int Value { get; set; }

    public static explicit operat或 FooObject(BarObject bar)
    {
        return new FooObject { Name = bar.Name, Value = bar.Value };
    }
}

class BarObject : IObject
{
    public string Name { get; set; }
    public int Value { get; set; }

    public static explicit operat或 BarObject(FooObject bar)
    {
        return new BarObject { Name = bar.Name, Value = bar.Value };
    }
}

现在请你写

var foo = new FooObject();
var bar = (BarObject)foo;

var bar = new BarObject();
var foo = (FooObject)bar;

without getting err或s.

如果你认为是自然的,也可以创建<条码>简单明了的转换。 E.g.int 即隐含的可兑换成double:int i = 5; Double x = i;

(This is also an answer to the closed question How do I cast Class FooObject to class BarObject which both implement interface IObject?).

不能从<条码>A到<条码>。 如果他们分享的都是共同的接口,除非你实际界定自己的转换操作者,假定你控制其中一种类型的来源,或者使用另一个由<does<>>/em>控制源的人提供的用户界定的转换。 (然而,这种用户界定的转换不会保留原标。) 其中一个物体被转换为另一个物体。

You can convert from A to Interface1, and B to Interface1. But two types simply sharing a common parent does not make those two types convertible to one another.

A a = new A(); 
B b = new B();
Interface1 obj1 = a; // legal
Interface1 obj2 = b; // legal
B obj3 = (B)a; // not legal, a is simply not a B

tobias86 put in well in a comment below, you have a cat and a dog. Both derive from Animal. But a cat just isn t a dog.


As an expansion, you might be struggling with how and why you would use an interface. You do not use an interface to substitute an A for a B, or a B for an A. You use it to substitute either A or B for Interface1. It s the interface you expect, and the A or B you might supply. Given:

public void DoSomething(Interface1 obj) { } // expects 
DoSomething(new A()); // you can supply A

public Interface1 GetSomething() // callers expect to get 
{
    return new B(); // you can supply a B
}

它是你们为方案拟定工作的接口,A和B只是执行。 你可能认为,你可以把B带给期望A的东西。 这种期望可能需要改变。

两种类型采用相同的接口(或具有相同的基类),并不能互换;<代码>A始终是<代码>A;<代码>B;<代码>始终是<代码>B。 在继承链中,可以把物体作为自己或母体。 你:

A : ISomeInterface
B : ISomeInterface

which lets you cast an A as A or ISomeInterface, and a B as B or ISomeInterface

or (depending on your meaning of "derived from")

SomeBaseType
 > A
 > B

允许您将<代码>A作为<代码>A或SomeBaseTypeB作为<代码>B或SomeBaseType

(plus object, in each case)

你们需要成为接口。

interface IBase { }
class A : IBase { }
class B : IBase { }

With this, the only thing the two types have in common is the interface members. B might have items that A does not.

A a = new A();
B b = new B();

IBase aBase = a;
IBase bBase = b;

那么,你就可以在<代码>上说任何东西。 IBase 接口。

When casting from A to B B must be a super type for A or the runtime type of the object must be B

class A : B{}

您可以把A至B类时间汇编成册。 如果物体的操作时间类型为A,你也可以投出一种B类物体。

在你的情况下,这两种类型的关系并不具有超级子类关系。 他们只有共同的超级类型,但还不够。

As an example of why this can t work (generically) how would you have the compiler cast from Point[] to a Dictionary<string,HashSet<byte>>? (both implement IEnumerable)

What you want to do doesn t make sense. objectA is not a B.

You can only cast them to the interface type. A is not B but they are both I. this means you can take A and cast to I or B and cast to I but not B and cast to A

following:

public interface Human
{
    bool Male { get; }
}

public class Man : Human
{
    public bool HasABeard { get { return true; } }

    public bool IsMale { get { return true; } }
}

public class Woman : Human
{
    public bool IsMale { get { return false; } }

    public List<Pair<Shoe>> Shoes { get; set; }
}

What would you expect the compiler to produce from the following code? What will the output be?

Man a;
Woman b = new Woman();
a = (Man)b;

Console.WriteLine(a.HasABeard ? "Beard ON" : "Beard OFF");

在接口中界定的静态通用方法的帮助下,可以通过反思取得预期结果:

 public interface IPerson
 {
     string Name { get; set; }
 
     static TDest ChangeType<TDest, TSource>(TSource source) where TSource : IPerson where TDest : IPerson, new()
     {    
         var instance = new TDest();
         foreach (var property in typeof(IPerson).GetProperties())
         {
             property.SetValue(instance, property.GetValue(source));
         }
         return instance;
     }
 }
 

执行<代码>IPerson的类别:

public class Worker : IPerson
{
    public string Name { get; set; }
}

public class Manager : IPerson
{
    public string Name { get; set; }
}

<><>Usage:

var worker = new Worker { Name = "John" };
var manager = IPerson.ChangeType<Manager, Worker>(worker);

替代使用<代码>Aggregate:

public interface IPerson
{
    string Name { get; set; }

    static TDest ChangeType<TDest, TSource>(TSource source) where TSource : IPerson where TDest : IPerson, new()
    {
        return typeof(IPerson).GetProperties()
                              .Aggregate(new TDest(), (dest, prop) => {
                                  prop.SetValue(dest, prop.GetValue(source));
                                  return dest;
                              });
    }
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签