网站服务费算什么费用,168推广,网上购物网站开发英文文献,网站app建设图片C# 8.0 默认接口实现IntroC# 8.0 开始引入了默认接口实现#xff0c;也就是可以在接口里写方法实现。在之前的版本中接口上是没有办法定义实现的#xff0c;方法也都是 public 的#xff0c;除了接口和属性之外是不能定义其他数据的#xff0c;这也意味着#xff0c;接口从… C# 8.0 默认接口实现IntroC# 8.0 开始引入了默认接口实现也就是可以在接口里写方法实现。在之前的版本中接口上是没有办法定义实现的方法也都是 public 的除了接口和属性之外是不能定义其他数据的这也意味着接口从一开始就要设计得比较好否则在已有接口里增加新方法的时候其实现就必须要修改否则就会编译失败默认接口实现使得可以不造成破坏性变更的前提下在接口中新增加方法只需要在接口中提供一个默认的实现即可。Sample下面我们来看一个示例吧internal interface IFly
{string Name { get; }
}
internal class Superman : IFly
{public string Name nameof(Superman);
}
internal class MonkeyKing : IFly
{public string Name nameof(MonkeyKing);
}
这是一个基本的接口定义并提供了两个实现紧接着我们来为接口新增一个方法internal interface IFly
{string Name { get; }void Fly() Console.WriteLine(${Name.GetValueOrDefault((DefaultName))} is flying);
}internal class Superman : IFly
{public string Name nameof(Superman);public void Test(){((IFly) this).Fly();Console.WriteLine(Name);}
}internal class MonkeyKing : IFly
{public string Name nameof(MonkeyKing);public void Fly(){Console.WriteLine($Im {Name}, Im flying);}
}
我们在接口里增加了一个 Fly 方法并提供了一个默认实现在其中一个实现中进行了重写我们来写一段代码测试一下吧// Cannot resolve symbol Fly
// new Superman().Fly();IFly fly new Superman();
fly.Fly();fly new MonkeyKing();
fly.Fly();
输出结果如下Superman is flying
Im MonkeyKing, Im flying
IFly
上面的示例中 Superman 没有定义 Fly 这个方法是不能直接调用 Fly 方法的需要先转成 IFly 接口然后再调用此时方法实现是在接口里定义的逻辑而 MonkeyKing 实现了 Fly 方法所以会使用它自己的 Fly 实现如上面所示。除了上面的基本用法之外现在可以在接口里定义静态字段静态方法来实现更好的方法复用我们在上面的示例里演示一下修改后的示例如下internal interface IFly
{private const string DefaultName nameof(IFly);protected static string GetDefaultName() DefaultName;public static string GetPublicName() DefaultName;// Interface cannot contain instance fields// private string name ;string Name { get; }void Fly() Console.WriteLine(${Name.GetValueOrDefault((DefaultName))} is flying);
}internal class MonkeyKing : IFly
{public string Name nameof(MonkeyKing);public void Fly(){Console.WriteLine($Im {Name}, Im flying, DefaultName:{IFly.GetDefaultName()});}
}
如果定义了 protected static 的方法或字段则在实现接口的类中就可以通过 IFly.GetDefaultName() 来调用接口中的方法了如果是 protected 就只能在实现它的类型中使用如果要在没有实现接口的类型中调用可以声明为 public 就可以了下面是在没有实现接口的类型中调用的示例// Cannot access protected method GetDefaultName here
// IFly.GetDefaultName().Dump();IFly.GetPublicName().Dump();
More虽然现在可以这样用但我个人还是推荐沿用之前的接口用法不要轻易使用这个特性提前设计提前规划才是正道不要想着事后补偿感觉这个特性比较合适的一个使用场景是现在基于接口的扩展方法扩展方法作为一个接口的默认实现具体类可以重写这个实现使用示例如下Taskbool SaveProperties(int id, Dictionarystring, object properties)
{if (properties is null || properties.Count 0) return Task.FromResult(false);var json JsonConvert.SerializeObject(properties.Select(p new PropertyModel(){PropertyName p.Key,PropertyValue p.Value?.ToString()}));return SaveProperties(id, json);
}Taskbool SaveProperties(int id, string properties);
在之前的版本中我一般都是把上面的方法作为一个扩展方法来用有个默认接口实现之后也可以考虑加一个默认实现仅限于业务代码中针对类库代码感觉还是越干净越好Referenceshttps://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/default-interface-methods-versionshttps://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#default-interface-methodshttps://github.com/WeihanLi/SamplesInPractice/blob/master/CSharp9Sample/DefaultInterfaceImplement.cs