0
点赞
收藏
分享

微信扫一扫

C#,入门教程——至关重要的预处理指令

大雁f 2022-04-18 阅读 54

Visual Studio、C#编译器以及C#语法所支持的预处理指令,绝对是天才设计
编译程序的时候会发现,程序可以编译成 bebug 和 release 模式,分别保存于相应的文件夹。
编写工业软件,一定有下面两个必然的需求。

一、调试与正式版本的区别

有些代码,仅用于调试模式,比如一些中间结果、调试信息的输出;而在正式版本,即release 版本中,这些代码不应该被编译。

二、不同版本的代码

工业软件的每一“段”代码,都属于“千锤百炼”,会有多个版本。
保存不同的版本,可以通过版本控制、文件控制等等很多方式。
但其中最有效与直接,程序员乐于接受的却是用“预处理指令”。

三、预处理指令的应用实例

这里应用网友 cjolj 原创的代码:
C#生成随机数之二 生成不重复的随机数https://blog.csdn.net/cjolj/article/details/59486865


第一版:假设先写了一个自认为不错的代码。

#if DEBUG
List<string> echo = new List<string>();
#endif

/// <summary>
/// 利用Hashtable
/// </summary>
static int[] UseHashTableToNonRepeatedRandom(int length, int minValue, int maxValue)
{
    Hashtable hashtable = new Hashtable();
    int seed =  Guid.NewGuid().GetHashCode();
    Random random = new Random(seed);
    for (int i = 0; hashtable.Count < length; i++)
    {
        int nValue = random.Next(minValue, maxValue);
        if (!hashtable.ContainsValue(nValue) && nValue != 0)
        {
            hashtable.Add(i, nValue);
#if DEBUG
			echo.Add(i + ",");
#endif
        }
    }
    int[] array = new int[hashtable.Count];
    hashtable.Values.CopyTo(array, 0);
    return array;
}

请注意其中的 #if DEBUG 和 #endif 语句。

这句话的意思是相应的代码仅仅出现于 调试版本。


第二版:经过测试,不算理想,有想到了新的思路。

淘汰第一版本,不要直接删除代码,用预处理指令包括起来即可。
后续讨论的时候,这个代码就在这里,无需从版本控制或其他文件中搜索。 

#if __SLOWEST_METHOD__

#if DEBUG
List<string> echo = new List<string>();
#endif

/// <summary>
/// 利用Hashtable
/// </summary>
static int[] UseHashTableToNonRepeatedRandom(int length, int minValue, int maxValue)
{
    Hashtable hashtable = new Hashtable();
    int seed =  Guid.NewGuid().GetHashCode();
    Random random = new Random(seed);
    for (int i = 0; hashtable.Count < length; i++)
    {
        int nValue = random.Next(minValue, maxValue);
        if (!hashtable.ContainsValue(nValue) && nValue != 0)
        {
            hashtable.Add(i, nValue);
#if DEBUG
			echo.Add(i + ",");
#endif
        }
    }
    int[] array = new int[hashtable.Count];
    hashtable.Values.CopyTo(array, 0);
    return array;
}
#endif

添加第二版本的代码:


#if __SECOND_SLOW_METHOD__

/// <summary>
/// 检查生成的随机数据是否重复
/// 如果重复则继续递归调用
/// 如果不重复则返回该数
/// </summary>
/// <param name="arr">生成的非重复随机数数组</param>
/// <param name="temp">随机数</param>
/// <param name="minValue">最大值</param>
/// <param name="maxValue">最小值</param>
/// <param name="random">生成随机数对象</param>
/// <returns>返回一个不重复的随机数</returns>
static int getNumberNonRepeatedRandom(int[] arr, int temp, int minValue, int maxValue, Random random)
{
    int n = 0;
    while (n <= arr.Length - 1)
    {
        if (arr[n] == temp) //利用循环判断是否有重复 
        {
            temp = random.Next(minValue, maxValue); //重新随机获取。 
            getNumberNonRepeatedRandom(arr, temp, minValue, maxValue, random);//递归:如果取出来的数字和已取得的数字有重复就重新随机获取。 
        }
        n++;
    }
    return temp;
}
/// <summary>
/// 递归,用它来检测生成的随机数是否有重复,
/// 如果取出来的数字和已取得的数字有重复就重新随机获取。
/// </summary>
static int[] RecursiveMethodToNonRepeatedRandom(int length, int minValue, int maxValue)
{
    int seed = Guid.NewGuid().GetHashCode();
    Random random = new Random(seed);
    int[] array = new int[length];
    int temp = 0;
    for (int i = 0; i < length; i++)
    {
		// 随机取数 
        temp = random.Next(minValue, maxValue); 
		// 取出值赋到数组中 
        array[i] = getNumberNonRepeatedRandom(array, temp, minValue, maxValue, random); 
    }
    return array;
}

#endif

第三版:一周以后,大家认为还不算很好,又有了新版本。


淘汰第二版本,也不要直接删除代码,继续用预处理指令包括起来即可。
后续讨论的时候,这个代码就在这里,无需从版本控制或其他文件中搜索。

#if __A_LITTLE_FAST_METHOD__

/// <summary>
/// 方法一
/// 使用随机抽取数组index中的数,填充在新的
/// 数组array中,使数组array中的数是随机的
/// 思路:用一个数组来保存索引号,先随机生成一个数组位置,
/// 然后把随机抽取到的位置的索引号取出来,
/// 并把最后一个索引号复制到当前的数组位置,
/// 然后使随机数的上限减一,具体如:先把这100个数放在一个数组内,
/// 每次随机取一个位置(第一次是1-100,第二次是1-99,...),
/// 将该位置的数用最后的数代替。
/// </summary>
static int[] UseDoubleArrayToNonRepeatedRandom(int length, int minValue, int maxValue)
{
    int seed = Guid.NewGuid().GetHashCode();
    Random radom = new Random(seed);
    int[] index = new int[length];
    for (int i = 0; i < length; i++)
    {
        index[i] = i + 1;
    }

	// 用来保存随机生成的不重复的数 
    int[] array = new int[length]; 
	// 设置上限 
    int site = length;             
	// 获取index数组中索引为idx位置的数据,赋给结果数组array的j索引位置
    int idx;                       
    for (int j = 0; j < length; j++)
    {
		// 生成随机索引数
        idx = radom.Next(0, site - 1);  
		// 在随机索引位置取出一个数,保存到结果数组 
        array[j] = index[idx];          
		// 作废当前索引位置数据,并用数组的最后一个数据代替之
        index[idx] = index[site - 1];   
		// 索引位置的上限减一(弃置最后一个数据)
        site--;                         
    }
    return array;
}
#endif

保留

#if __A_LITTLE_FAST_METHOD__

#endif

是因为这个算法属于一般,有更好的第四、第五版本。。。。。。

再一次感谢 网友 cjolj 的代码!

预处理指令是值得你好好体会的。

又及:

具有下面两个特点的程序员(或者书籍、教材等等):

(1)代码中出现 Console语句;

(2)没有预处理指令;

属于没开窍的旱鸭程序员

--------------------------------------------------------
POWER BY TRUFFER.CN

举报

相关推荐

0 条评论