【问题标题】:Creating an instance of a interface in c#在 C# 中创建接口的实例
【发布时间】:2013-07-17 19:24:53
【问题描述】:

我在 C# 中使用一个接口,而不是编写一个实现该接口的全新类,是否可以只创建一个实现该接口的对象?接口定义为

public interface ITokenStore
{

    IToken CreateRequestToken(IOAuthContext context);


    IToken CreateAccessToken(IOAuthContext context);
}

而且我知道在 java 中我可以使用类似的东西

ITokenStore tokenStore = new ITokenStore()
    {
        IToken CreateRequestToken(IOAuthContext context) {
            IToken requestToken = null;

            return requestToken;
        }

        IToken CreateAccessToken(IOAuthToken context) {
            IToken accessToken = null;

            return accessToken;
        }
    };

是否有等效的方法在 c# 中的接口实例中实例化?

【问题讨论】:

  • Java 仍在幕后创建一个类,它只是语法糖 - 在某种程度上,它们解决了缺少委托/函数指针的问题。
  • 使用模拟框架,您可以创建一个实例,例如new Mock<ITokenStore>()。您可能希望设置模拟框架可能从委托执行的方法的具体实现。

标签: c# interface


【解决方案1】:

“在 c# 中创建接口的实例”的唯一方法是创建实现接口的类型的实例。

【讨论】:

  • 它将被编译为匿名类。
  • 不,您不能在 .NET/C# 中执行此操作,并且需要明确的是,您也无法在 Java 中执行此操作。编译器在 Java 中所做的是为您构建匿名类型,实现接口的类型。所以 Java 有一个获取该类型的捷径,而 C# 没有。
  • @LasseV.Karlsen 虽然C# 可能不会,但 MS 的 C# 编译器可以:请参阅下面的 Oakio 答案。它不是任何规范的一部分(而且它的使用最多是有限的),所以使用它真的不是一个好主意。
【解决方案2】:

接口在设计上没有逻辑。他们实际上什么都不做。

在没有实现类的情况下实例化一个甚至没有意义

【讨论】:

    【解决方案3】:

    如果你真的想要这个:

        private static void Main(string[] args)
        {
            IFoo foo = new IFoo(); // <- interface
            foo.Print();
    
            Console.ReadKey();
        }
    
    
        [ComImport, Guid("A7D5E89D-8FBD-44B7-A300-21FAB4833C00"), CoClass(typeof(Foo))]
        public interface IFoo
        {
            void Print();
        }
    
        public class Foo : IFoo
        {
            public void Print()
            {
                Console.WriteLine("Hello!");
            }
        }
    

    但是如果你在ildasm.exe打开编译的程序集,你会看到:

    IL_0001: newobj instance void TestApp.Program/Foo::.ctor()

    【讨论】:

      【解决方案4】:

      据我所知,.NET 没有匿名内部类的 Java 概念。在单元测试场景中,通常需要动态实现接口。例如,看看一些动态模拟框架可能会让你感兴趣,例如

      1. Impromptu Interface(包括对动态的支持)
      2. Moq

      在 NuGet 库中查看带有 mocking 标记的包。

      【讨论】:

        【解决方案5】:

        您不能在 C# 中创建接口的实例。您必须创建实现该接口的类/类型的实例。

        可能想继续阅读interfaces in C#。没有办法像 Java 那样“伪造”它。

        如果我对这个概念很感兴趣,我很高兴,因为它是另一种语言的东西。如果您的消费者知道如何伪造duck typing,我想您可以使用带有委托参数的匿名类。但这似乎不值得。

        【讨论】:

          【解决方案6】:

          类似这样的:

          public class MyTokenStore: ITokenStore
          {
              public IToken CreateRequestToken(IOAuthContext context)
              {
                  ...some code here...
              }
              public IToken CreateAccessToken(IOAuthContext context)
              {
                  ...some code here...
              }
          }
          

          然后使用它:

          ITokenStore x = new MyTokenStore();
          

          【讨论】:

            【解决方案7】:

            正如其他人所说,不,这是不可能的。

            但是,您可以编写一个通用类,其中每个方法都有委托。类似于以下内容:

            public class DelegateTokenStore : ITokenStore
            {
                public delegate IToken TokenCreator(IOAuthContext context);
                public TokenCreator RequestTokenCreator { get; set; }
                public TokenCreator AccessTokenCreator { get; set; }
            
                public IToken CreateRequestToken(IOAuthContext context)
                {
                    return RequestTokenCreator(context);
                }
            
                public IToken CreateAccessToken(IOAuthContext context)
                {
                    return AccessTokenCreator(context);
                }
            }
            

            那么你可以这样使用它:

            ITokenStore tokenStore = new DelegateTokenStore()
            {
                RequestTokenCreator = (context) =>
                {
                    IToken requestToken = null;
                    return requestToken;
                },
                AccessTokenCreator = (context) =>
                {
                    IToken accessToken = null;
                    return accessToken;
                },
            };
            

            我并不是说采用这种方法一定是个好主意。与任何事情一样,适当性取决于您的用例。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-10-30
              • 2013-02-17
              • 2012-01-19
              • 1970-01-01
              • 1970-01-01
              • 2016-08-13
              相关资源
              最近更新 更多