当前位置:蜘蛛资讯网首页>莫扎特>清明节

乌海敌芭拙科技

书名:德清源穆迸网络技术贝博软件下载|作者:笑无语|本书类别:古言|更新时间:05:07:16|字数:3896字

去年12月份,随着Visual Studio 2017 Update 15.5的发布,Visual C#迎来了它的最新版本:7.2. 在这个版本中,有个让人难以理解的新特性,就是private protected访问修饰符(Access Modifier)。至此,C#语言的访问修饰符有以下几种:

  • private
  • protected
  • public
  • internal
  • internal protected
  • private protected

既然有了private和protected,那么private protected又是什么?它跟internal protected又有什么关系?本文简单介绍一下。

private protected是怎么回事

在解释private protected之前,首先让我们回顾一下internal protected访问修饰符。internal protected表示,相同程序集(Assembly)中的其它类型,或者当前类的子类,具有访问该类中internal protected成员的能力,可以用下图表示:

image

在上图中:

  • 程序集A中的X类,可以访问A类中的Method方法
  • 程序集A中的B类,可以重载A类中的Method方法,B类中的其它成员也可以访问A类中的Method
  • 程序集B中的C类,可以重载A类中的Method方法,C类中的其它成员也可以通过base.Method()访问A类中的Method
  • 程序集B中C类的Method方法重载了A类的Method方法,因此,internal关键字被去掉,于是,程序集B中的Y类,无法访问C类中的Method方法

因此,internal protected表示internal或者protected。

然而,private protected表示,仅有相同程序集(Assembly)中继承于当前类型的类,才能访问该类中private protected成员。换句话说,private protected就是访问者必须在相同程序集中(internal),同时还必须是被访问类型的子类(protected),可以用下图表示:

image

因此,private protected表示internal并且protected。

private protected何时使用

理论上讲,private protected完善了C#语言的封装性,提供了另一层级别的成员访问保护,听起来感觉让人费解又没什么用。那么,什么时候使用这个访问修饰符呢?现假设你正在设计一个框架,其中有个类,它提供对象存储功能,它的职责是保存给定的对象,而它的每一种实现都需要依赖于一个对象的序列化机制,比如:

public sealed class SerializationHelper
{
    public string Serialze(object s)
    {
        using (var memoryStream = new MemoryStream())
        {
            var serializer = new XmlSerializer(s.GetType());
            serializer.Serialize(memoryStream, s);
            return Encoding.UTF8.GetString(memoryStream.ToArray());
        }
    }
}

public abstract class DataStorage
{
    private readonly SerializationHelper serializer = new SerializationHelper();
    protected SerializationHelper Serializer => serializer;
    protected abstract void SaveObject(object obj);
}

public sealed class InMemoryDataStorage : DataStorage
{
    private readonly List serializedData = new List();
    protected override void SaveObject(object obj) 
        => serializedData.Add(Serializer.Serialze(obj));
}

上面的代码中,SerializationHelper提供了一种将对象序列化成XML字符串的机制;DataStorage是所有对象数据存储的基类,它当然也为其子类提供了一个访问对象序列化器的方式。由于这个对象序列化器是提供给其子类调用的,因此,DataStorage中的Serializer属性是protected的。最后,InMemoryDataStorage继承了DataStorage,通过调用由基类提供的Serializer属性,实现了SaveObject方法。

整个实现当然没有问题。可是,通过审核所有类型的可见性,我们发现,我们不打算将SerializationHelper这个类暴露给外界,也就是不希望其它的程序集能够直接访问SerializationHelper类,于是,我们将它设置成internal的。也就是:

internal sealed class SerializationHelper
{
    public string Serialze(object s)
    {
        using (var memoryStream = new MemoryStream())
        {
            var serializer = new XmlSerializer(s.GetType());
            serializer.Serialize(memoryStream, s);
            return Encoding.UTF8.GetString(memoryStream.ToArray());
        }
    }
}

好了,问题来了,编译器开始抱怨了,说SerializationHelper类的访问级别比DataStorage.Serializer属性的访问级别要低:

image

道理显而易见:DataStorage.Serializer属性在DataStorage的子类中即可访问,这个子类可以是在DataStorage所在的程序集中,也可以是在另一个程序集中。然而,这个属性的依赖类型:SerializationHelper类,却只能在DataStorage所在的程序集中才能被访问。

于是,能量巨大的private protected闪亮登场。将DataStorage.Serializer属性的访问修饰符从protected改为private protected,问题就解决了:

internal sealed class SerializationHelper
{
    public string Serialze(object s)
    {
        using (var memoryStream = new MemoryStream())
        {
            var serializer = new XmlSerializer(s.GetType());
            serializer.Serialize(memoryStream, s);
            return Encoding.UTF8.GetString(memoryStream.ToArray());
        }
    }
}

public abstract class DataStorage
{
    private readonly SerializationHelper serializer = new SerializationHelper();
    private protected SerializationHelper Serializer => serializer;
    protected abstract void SaveObject(object obj);
}

public sealed class InMemoryDataStorage : DataStorage
{
    private readonly List serializedData = new List();
    protected override void SaveObject(object obj) 
        => serializedData.Add(Serializer.Serialze(obj));
}

不过,一旦使用了private protected访问修饰符,DataStorage.Serializer属性就只能在DataStorage所在的程序集的子类中访问了。

private protected如何使用

private protected访问修饰符是C# 7.2的新特性。自从使用Roslyn编译器服务的C# 6.0开始,C#编译器的版本更新就可以与.NET Framework和Visual Studio的发布分离开来了。这一点在C# 7.x(包括7.1和7.2)的发布中逐步显现出来。在Visual Studio 2017的编译高级选项中,开发人员可以很方便地选择所需的C#版本:

image

如上图所述,在C#项目上点右键,在项目属性的Build标签页中,点击Advanced按钮,在Advanced Build Settings对话框中,通过Language version下拉框来选择所需的C#语言版本。其中:

  • C# latest major version (default):C#最新的主版本,也就是与Visual Studio一起发布的主要版本,在VS2017上对应C# 7.0
  • C# latest minor version (latest):C#的最新版,通常通过VS2017的升级包获得

要使用private protected访问修饰符,则需要在此选择C# latest minor version (latest),或者C# 7.2.

总结

本文对C# 7.2的新特性:private protected访问修饰符进行了解析,并通过案例来说明它的应用场景以及Visual Studio 2017对于C#新特性的支持。

zong jie ben wen dui C 7. 2 de xin te xing: private protected fang wen xiu shi fu jin xing liao jie xi, bing tong guo an li lai shuo ming ta de ying yong chang jing yi ji Visual Studio 2017 dui yu C xin te xing de zhi chi.

打赏
神奇推荐位
  • 陈嘉上被曝恋女星

    灯盏香客?/?着

    “衡大叔,大家都说三十来岁正是男人如狼似虎的年纪”“所以呢?”“我觉得这句话说得很对...

  • 皇家社会主帅下课

    浮梦公子?/?着

    其实这不过是一场由腹黑皇帝和狡黠恶女定下的一个约盟继而引发的一个故事!人人皆道,将军...

  • 库尔勒泼锨传媒

    暮夜寒?/?着

    【种田】+【空间】+【温馨】+【致富】+【虐渣】被炸成灰灰的莫颜重生到了古代,成了正...

  • 新余闯驼凡培训学校

    悠然世?/?着

    本书出版名《美人思无邪》,天猫购买地址=a1z10.1-b.w11350767-15...