接口实例

我是C#.net的新手,很惊讶地知道可以创建一个接口的实例
Iinterface myDimensions = (Iinterface) myBox;
如何为这种类型的语句分配内存?是在堆上分配内存吗? 任何人都可以给出使用这种类型的实例化的任何情况。   实现接口的类可以显式实现该接口的成员。显式实现成员时,不能通过类实例访问它,而只能通过接口的实例访问它。 为什么在语言中强制执行这样的约束? 谢谢,     
已邀请:
在回答您的第一个问题之前,我注意到您在这里有两个问题。在将来,当您有两个问题时,请考虑在Stack Overflow上提出两个单独的问题。您可能已经注意到,当您在一个问题中提出两个问题时,几乎每个人都会忽略第二个问题。   我很惊讶地知道可以像创建接口的实例一样
Iinterface myDimensions = (Iinterface) myBox; 
  如何为这种类型的语句分配内存?是在堆上分配内存吗? 正如其他人所指出的,这不一定是创建实现接口的类型实例。每个人似乎已经忘记了他们急于告诉你引用转换不分配内存,拳击转换确实分配内存。如果myBox是结构类型,那么这将在堆上为“包装器”分配内存,并在包装​​器中复制该值。然后包装器实现接口。 继续你的第二个问题:   实现接口的类可以显式实现该接口的成员。显式实现成员时,不能通过类实例访问它,而只能通过接口的实例访问它。为什么在语言中强制执行这样的约束? 显式接口实现的目的是使类能够实现特定接口,而不要求这些方法出现在不需要的地方。例如,假设你有:
class MyConnection : IDisposable
{
    public void OpenConnnection() { ... }
    public void CloseConnection() { ... }
    public void Dispose() { ... CloseConnection(); ... }
}
如果处理开放连接与关闭连接相同,那么您可能不希望通过以下两种方法混淆用户:(1)使用两种方法执行相同操作,或者(2)使用方法OpenConnection与非显而易见性配对像Dispose这样的名字。通过使Dispose“隐藏”,除非将对象转换为IDisposable,然后让用户更容易发现正确的事情。 您使用此方法的另一种情况是,当您有两个具有相同名称的接口时:
interface IFoo { void M(); }
interface IBar { void M(); }
现在,如何创建一个实现IFoo和IBar的C类,但是对于这两个M方法有不同的实现?如果您需要两个不同的实体,则必须对其中一个或两个使用显式实现。     
那不是实例化 - 它是一个类型转换。实例是原始对象,即
myBox
。至于内存,是的,为引用分配了内存 - 无论是在堆上还是堆栈完全取决于上下文。在你的例子中(看起来像是在函数中),我猜是堆栈。 关于显式实现:语言特性允许单个类实现包含具有完全相同签名的一个或多个成员的两个或更多个接口。例如:
interface A
{
   void Foo();
}

interface B
{
   void Foo();
}

class C : A, B
{
   void A.Foo()
   {
   }

   void B.Foo()
   {
   }
}
没有这个功能,编译器不清楚接口成员
C.Foo
实现了什么。当然,需要注意的是,调用者不能简单地调用
C.Foo
,因为调用哪种方法也不明显;因此,必须首先将
C
类型的对象转换为
A
B
,以使程序员的Foo-lish意图明确。     
你拥有的是一个演员,而不是一个实例。在这种情况下,必须在其他地方创建对象:
// Allocate memory on the stack to point to the location on the heap
// to store the object and create the object on the heap.
Box box = new Box();

// Allocate memory on the stack to point to the location on the heap
// and point it to the already existing object on the heap.
IInterface iBox = (IInterface)box;
您从MSDN引用的引用是对显式接口实现的引用。这些可能有点令人困惑。一个简单的例子是最简单的:
public interface ISomething
{
    void SayHi();
}

public class Something : ISomething
{
    public void SayHi() { Console.WriteLine("Hello World!"); }

    public void ISomething.SayHi() { Console.WriteLine("42!"); }
}
现在您的代码可以具有以下内容:
Something obj = new Something();

// Outputs "Hello World!"
obj.SayHi();

ISomething iObj = obj;

// Outputs "42!"
iObj.SayHi();
在那个例子中,内存的工作方式与我最初解释的相同。     
你的陈述
Iinterface myDimensions = (Iinterface) myBox;
它没有创建任何东西,它将对象myBox(必须在某处实例化)转换为Iinterface类型,并将myDimesions指向该对象。     
interface
的MSDN C#参考中的语言有点误导。当它表示接口的实例时,它实际上意味着对接口的引用,您可以通过将对象(即,类的实例)转换为接口类型来获得该接口。 可以隐式实现或显式实现接口成员。当它明确实现时,接口名称用于限定它:
public class Box: IInterface
{
   void IInterface.Foo() { ... }
}
这会将成员隐藏在公共类接口中。这样做的一个原因是版本控制,就像类已经有一个不相关的
Foo()
方法。为了指定
IInterface.Foo()
而不是
Box.Foo()
,唯一的方法是通过引用它或通过声明为
IInterface
的变量来引用
IInterface
。你可以很容易地拥有这个:
 IInterface myDimensions = myBox; //no casting needed
 myDimensions.Foo(); //calls Box.IInterface.Foo() and NOT Box.Foo()
    
宣言:
interface IMy
{
    void OhMy();
}

class Explicit : IMy
{
    public void IMy.OhMy() { }
}

class Implicit : IMy
{
    public void OhMy() { }
}
用法:
Implicit i = new Implicit();
i.OhMy(); // ok

Explicit e = new Explicit();
e.OhMy(); // it cannot be accessed through a class instance
((IMy)e).OhMy(); // but only through an instance of the interface

IMy my = new Explicit();
my.OhMy(); // ok
    
基本上你有一个由变量名称调用“myBox”指向的对象X.对象内存分配取决于您创建此对象X的方式。 代码: Iinterface myDimensions =(Iinterface)myBox; 只将您的对象X分配给“myDimensions”变量。由于此变量是Iinterface,您必须使用(Iinterface)来强制转换它。这是一种类型安全功能,可以强制您了解您正在处理的对象类型。 到目前为止,您至少有两个变量“myBox”和“myDimensions”指向对象X. 您可以创建任意数量的变量,指向此对象。如果myBox的变量类型没有实现“Iinterface”,你将需要在赋值期间将“myBox”强制转换为“myDimensions”,即使你的对象X支持Iinterface。 另外,变量也会占用内存,因为它需要存储实际实例的地址     
  任何人都可以给出使用这种类型的实例化的任何情况。 正如其他人所说,这不是真正的实例化。至于它的用法,一个例子是你实际上看不到的,因为它发生在封面下。考虑using语句
using (DisposableObject foo = new DisposableObject())
{
   // doing things with foo
}
以及编译器如何评估该表达式并将其转换为类似的表达式
DisposableObject foo = null;
try 
{
   foo = new DisposableObject();
   // doing things with foo
}
finally
{
   if (foo != null)
   {
       ((IDisposable)foo).Dispose();
   }
}
或者考虑方法在接口类型而不是类中接受的其他方案。这是因为您可以有多个类来实现这样的接口,但该方法只关心这些类的对象是否满足接口的约定。
public void Dance(ICanDance dancer, bool wantTo)
{
     if (wantTo)
         dancer.Dance();
}
实际的舞者可以是实现界面的任何东西,无论是
LipSynchingPopSinger
StageDancer
还是
GuyThatIsNotTheFather
。     

要回复问题请先登录注册