Jayson_Dai 2021-12-24 14:55 采纳率: 66.7%
浏览 78
已结题

C# 静态类调用静态函数的问题

C#语言,我在写一个字符串处理的程序,要用到自己定义的一些元字符来分割、解析字符串;
我的想法是把我自己定义的元字符放进静态类里面,用字典字段来储存
有一个Meta类,里面放一些通用定义的元字符
有其他的类,除了放通用的元字符,还要加一些各自额外的的元字符
这些存元字符的静态类,都有一个自检是否有字典值冲突的静态方法MarkerUniqueCheck()
我希望所有的MarkerUniqueCheck()能够公用,不想每个类里面都各自实现一遍,我能想到的办法是从其他类里面,都调用某一个类的同名方法。
当前我写了2个类:Meta 和 MetaStep,我在Main()里面试了一下,但是试下来的结果我有不理解的地方。
先贴我的代码:

// Meta类,字段marker储存我自己定义的元字符,字段cName来储存当前类名
public static class Meta
    {
        public static readonly string cName = "Meta";
        public static readonly Dictionary<string, string> marker = new Dictionary<string, string>
        {
            {"mkFileDeli",  "-"},
            {"mkRegion",    "#"}, 
            {"mkItem",      "."},
            {"mkFmtHead",   "<"}, 
            {"mkFmtTail",   ">"}, 
            {"mkArguHead",  "{"}, 
            {"mkArguTail",  "}"},  
        };

        public static int MarkerUniqueCheck(out List<string> str_err)
        {
            int err = 0;
            str_err = new List<string>() {cName + " have " + marker.Count + " markers"};

            int nMk = marker.Count;

            List<string> mkKeys = marker.Keys.ToList<string>();
            List<string> mkVals = marker.Values.ToList<string>();
            for (int i = 0; i < nMk; i++)
            {
                for (int j = i + 1; j < nMk; j++)
                {
                    if (mkVals[i] == mkVals[j])
                    {
                        err = -1;
                        str_err.Add(mkKeys[i] + " and " + mkKeys[j] + " have the same value: \'" + mkVals[i] + '\'');
                    }
                }
            }

            return err;
        }
    }


// MetaStep类,与Meta成员一样,但是在构造函数里面增加额外的marker内容
// MarkerUniqueCheck()方法,因为跟Meta类的一样,我不想再写一遍,我采用了直接调用Meta类的同名方法的办法
public static class MetaStep
    {
        public static readonly string cName = "MetaStep";
        public static readonly Dictionary<string, string> marker = Meta.marker;
        static MetaStep()
        {
            cName = "MetaStep";
            Dictionary<string, string> extra = new Dictionary<string, string>
            {
                {"mkRefFileHead",   "《" },
                {"mkRefFileTail",   "》" },
                {"TempTest",        "#" }
            };
            foreach (KeyValuePair<string, string> kvp in extra)
            { marker.Add(kvp.Key, kvp.Value); }
        }

        public static int MarkerUniqueCheck(out List<string> str_err)
        {
            return Meta.MarkerUniqueCheck(out str_err);
        }

    }


// Main()里面的调用代码:
static void Main()
        {
            // ...
            Console.WriteLine(Meta.cName + ".MarkerUniqueCheck Error Id: " + Meta.MarkerUniqueCheck(out List<string> err_str));
            foreach(string str in err_str)
            { Console.WriteLine(str); }
            Console.WriteLine();

            Console.WriteLine(MetaStep.cName + ".MarkerUniqueCheck Error Id: " + MetaStep.MarkerUniqueCheck(out err_str)); //此处原来键入的是Meta.Meta.MarkerUniqueCheck(),输错了
            foreach (string str in err_str)
            { Console.WriteLine(str); }
            // ...
        }

运行结果:
Meta.MarkerUniqueCheck Error Id: 0
Meta have 7 markers
MetaStep.MarkerUniqueCheck Error Id: -1
Meta have 10 markers
mkRegion and TempTest have the same value: '#'

我不理解的地方在于输出结果的第4行,输出的是"Meta"而不是"MetaStep"
因为第5行的输出说明,MetaStep.MarkerUniqueCheck 调用 Meta.MarkerUniqueCheck时,用的字段marker是MetaStep类的,但是字段cName却用的是Meta类的

有没有人可以答疑一下?

----------------更新分界线------------------
我更新了我的方法Meta.MarkerUniqueCheck(),方便测试输出,直接写了2个WriteLine():

public static int MarkerUniqueCheck(out List<string> str_err)
        {
            int err = 0;
            str_err = new List<string>() {cName + " have " + marker.Count + " markers"};
            int nMk = marker.Count;

            Console.WriteLine(cName);
            Console.WriteLine(nMk);

            List<string> mkKeys = marker.Keys.ToList<string>();
            List<string> mkVals = marker.Values.ToList<string>();
            for (int i = 0; i < nMk; i++)
            {
                for (int j = i + 1; j < nMk; j++)
                {
                    if (mkVals[i] == mkVals[j])
                    {
                        err = -1;
                        str_err.Add(mkKeys[i] + " and " + mkKeys[j] + " have the same value: \'" + mkVals[i] + '\'');
                    }
                }
            }

            return err;
        }

简化了Main里面的调用:

static void Main()
        {
            // ...
            Meta.MarkerUniqueCheck(out List<string> err_str);
            MetaStep.MarkerUniqueCheck(out err_str);
            //...
        }

实际输出结果:
Meta
7
Meta
10

二我期待的输出结果是:
Meta
7
MetaStep
10

或者是下面的结果,至少不会让我产生疑惑:
Meta
7
Meta
7

  • 写回答

4条回答 默认 最新

  • CSDN专家-showbo 2021-12-24 16:19
    关注
    1. 为什么输出2个Meta,因为MetaStep.MarkerUniqueCheck这个方法也是调用的Meta.MarkerUniqueCheck这个方法,Meta.MarkerUniqueCheck静态方法中cName就是Meta中定义的cName = "Meta"这个值,这个不难理解吧?

    2. 为什么第四个是10,因为MetaStep的marker引用到了Meta中的marker,public static readonly Dictionary<string, string> marker = Meta.marker;
      marker是对象,为地址引用,MetaStep的静态构造函数中对marker 进行了修改,所以MetaStep和Meta中的2个maker变量都会一起变化。所以变成了10。

    地址引用意思就是Meta.marker和MetaStep.marker相当于指针,指向同一个地址的数据块,这2个变量任意修改其中一个,都会同时变化。但是需要注意是修改,而不是重新赋值,重新赋值的话将会指向另一个地址的数据块,此时就不相关了,在修改不会相互影响

    img


    有帮助或启发麻烦点下【采纳该答案】,谢谢~~有其他问题可以继续交流~

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 12月28日
  • 已采纳回答 12月24日
  • 赞助了问题酬金 12月24日
  • 修改了问题 12月24日
  • 展开全部

悬赏问题

  • ¥15 Python爬取指定微博话题下的内容,保存为txt
  • ¥15 vue2登录调用后端接口如何实现
  • ¥65 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?