C#,初学琼林(01)——绝对值(Absolute Value)计算的源代码进化过程及编程的基本范式

Posted 深度混淆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#,初学琼林(01)——绝对值(Absolute Value)计算的源代码进化过程及编程的基本范式相关的知识,希望对你有一定的参考价值。

强烈建议在 WinForm 编程,千万不要用 Console 终端编程,否则局限性太大了。

一、基础知识

1.1 Absolute Value at Wiki

In mathematics, the absolute value or modulus of a real number x, denoted |x|, is the non-negative value of x without regard to its sign. Namely, |x|=x if x is a positive number, and |x|=-x if x is negative (in which case negating x makes -x positive), and |0|=0. For example, the absolute value of 3 is 3, and the absolute value of −3 is also 3. The absolute value of a number may be thought of as its distance from zero.

在数学中,实数x的绝对值或模,表示为|x|,是x的非负值,而不考虑其符号。也就是说,如果x是正数,|x|=x,如果x为负数,|x|=-x(在这种情况下,x为负数使-x为正数),|0|=0。例如,3的绝对值为3,−3的绝对值也是3。一个数字的绝对值可以被认为是它离零的距离。

1.2 编程 = 逻辑

绝对值的逻辑是:如果x是正数,|x|=x,如果x为负数,|x|=-x

二、编程之旅

1.1 搭建合适的编程环境

点击下面的链接学习(动画演示,步步未惊心!):

C#,入门教程(02)—— Visual Studio 2022开发环境搭建图文教程https://blog.csdn.net/beijinghorn/article/details/123434181

1.2 基本代码——第一块砖

本段代码实现绝对值计算的逻辑。

private void button1_Click(object sender, EventArgs e)

    // 给出一个初值
    int a = 19; 
    // 保存绝对值的变量
    int b;
    // 计算绝对值的逻辑
    if (a < 0) b = -a;
    else b = a;

    // 显示计算结果
    string s = "a = " + a + "\\n";
    s += "|a| = " + b;

    MessageBox.Show(s, "绝对值计算");


计算结果是:

1.3 灵活代码——机制砖

初始值是一个固定的值。咱们来一个稍微有趣一点的。

private void button1_Click(object sender, EventArgs e)

    // 定义一个随机发生器(类似于彩票摇奖机)
    Random rand = new Random();
    // 生成一个随机初值(-50...50之间)
    int a = rand.Next(100) - 50;
    // 保存绝对值的变量
    int b;
    // 计算绝对值的逻辑
    if (a < 0) b = -a;
    else b = a;

    // 显示计算结果
    string s = "a = " + a + "\\n";
    s += "|a| = " + b;

    MessageBox.Show(s, "绝对值计算");

某次(因为每次都可能不同)计算结果:

 通过这段代码,咱们还学到了 随机数

1.4 简约代码——木砖

这么简单的事,有必要写这么多行代码?

private void button1_Click(object sender, EventArgs e)

    // 定义一个随机发生器(类似于彩票摇奖机)
    Random rand = new Random();
    // 生成一个随机初值(-50...50之间)
    int a = rand.Next(100) - 50;
    // 计算绝对值的逻辑
    int b = (a < 0) ? -a : a;
    // 显示计算结果
    string s = "a = " + a + "\\n|a| = " + b;
    MessageBox.Show(s, "绝对值计算");

1.5 函数(方法)来了——预制块

以上的代码只能出现于教室。编程的基本思路之一就是“做同样的事,都写成函数”。

函数(方法)是实现一小部分程序逻辑的功能性代码组。

/// <summary>
/// 生成一个随机数
/// (-n/2...n/2之间)
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
private static int RandNumber(int n)

    // 定义一个随机发生器(类似于彩票摇奖机)
    Random rand = new Random((int)DateTime.Now.Ticks);
    // 加一点点延迟,否则两个随机数会一样!
    Thread.Sleep(10);
    // 生成一个随机初值(-n/2...n/2之间)
    return rand.Next(n) - (n / 2);


/// <summary>
/// 计算绝对值的函数(方法)
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public static int Abs(int a)

    return (a < 0) ? -a : a;


private void button1_Click(object sender, EventArgs e)

    int a1 = RandNumber(100);
    int a2 = RandNumber(100);
    string s = "";
    s += "a1 = " + a1 + "\\n|a1| = " + Abs(a1) + "\\n";
    s += "a2 = " + a2 + "\\n|a2| = " + Abs(a2);
    MessageBox.Show(s, "绝对值计算");

因为想生成多个随机数,所以需要一个“生成随机数的函数”,RandNumber;

因为需要计算多个数值的绝对值,所以需要一个“计算绝对值的函数” Abs;

希望以上的代码,使得你能学到:

(1)怎么把重要的、重复的是都写成函数!

(2)怎么生成真正的(相对而言)随机数!

1.6 打包的函数——预制件

把一些相关的函数(方法,Method)及其他信息写在一个程序,就是类(class)。多个类可以组成命名空间(namespace),一个或多个命名空间可以组合成一个包,就是函数库(组件)。

namespace Legalsoft.Math

    public static class EMath
    
        /// <summary>
        /// 生成一个随机数
        /// (-n/2...n/2之间)
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static int RandNumber(int n)
        
            // 定义一个随机发生器(类似于彩票摇奖机)
            Random rand = new Random((int)DateTime.Now.Ticks);
            Thread.Sleep(10);
            // 生成一个随机初值(-n/2...n/2之间)
            return rand.Next(n) - (n / 2);
        

        /// <summary>
        /// 计算绝对值的函数(方法)
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public static int Abs(int a)
        
            return (a < 0) ? -a : a;
        
    


button1_Click(...) 就写成:

using Legalsoft.Math;


private void button1_Click(object sender, EventArgs e)

    int a1 = EMath.RandNumber(100);
    int a2 = EMath.RandNumber(100);
    string s = "";
    s += "a1 = " + a1 + "\\n|a1| = " + EMath.Abs(a1) + "\\n";
    s += "a2 = " + a2 + "\\n|a2| = " + EMath.Abs(a2);
    MessageBox.Show(s, "绝对值计算");

1.7 函数库(组件)来了——预制建筑

如果每个类、函数、命名空间、函数库都这么写,开发效率就太低了。此谓之“重复造车轮”。

C/C++,C#,Java 等编程语言都有极其丰富的“函数库(组件)”供大家使用。

/// <summary>
/// 生成一个随机数
/// (-n/2...n/2之间)
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
private static int RandNumber(int n)

    // 定义一个随机发生器(类似于彩票摇奖机)
    Random rand = new Random((int)DateTime.Now.Ticks);
    Thread.Sleep(10);
    // 生成一个随机初值(-n/2...n/2之间)
    return rand.Next(n) - (n / 2);


private void button1_Click(object sender, EventArgs e)

    int a1 = RandNumber(100);
    int a2 = RandNumber(100);
    string s = "";
    // 实际上,无需自行编写 Abs 函数,Math 函数库就有!
    s += "a1 = " + a1 + "\\n|a1| = " + Math.Abs(a1) + "\\n";
    s += "a2 = " + a2 + "\\n|a2| = " + Math.Abs(a2);
    MessageBox.Show(s, "绝对值计算");

上面代码,去掉了 Abs 函数,因为 C# 语言的(内部,听起来很高级!)函数库就有啊。

以后可用从一下几个方面获得函数库:

(1)自己编写的,日积月累的;

(2)小组或团队编写的,月累日积的;

(3)网络开源的;强烈推荐 NuGet !

(4)闭源的,无法看到源代码;

(5)未经允许的反编译获得,小人之为!

如何在 C# 中操纵“绝对”和“自相关”安全描述符?

【中文标题】如何在 C# 中操纵“绝对”和“自相关”安全描述符?【英文标题】:How are "absolute" and "self-relative" security descriptors manipulated in C#? 【发布时间】:2012-08-01 13:20:16 【问题描述】:

我正在玩弄code from here,它使用RawSecurityDescriptor 类从 Windows 注册表读取安全描述符,对其进行更改,然后将更改后的描述符存储回来。这与“dcomperm”Microsoft SDK 示例的作用基本相同。

然而,“dcomperm”样本进行了两次转换——一旦从注册表中读取描述符,它就会使用MakeAbsoluteSD()从“selt-relative”转换为“absolute”,然后以这种形式进行更改,一旦更改完成使用MakeSelfRelativeSD() 转换回“自相关”并以“自相关”形式存储。

在我链接到的代码中没有这样的转换。

它们是如何在 C# 中完成的?它们是由 .NET 框架在内部完成,还是我必须使用 P/Invoke 自己完成?

【问题讨论】:

【参考方案1】:

据我了解,System.Security.AccessControl 命名空间中的类(如RawSecurityDescriptorRawAcl 等)提供了相应 Win32 构造中信息的托管表示。所以RawSecurityDescriptor 的一个实例是一个.NET 对象,其字段也是.NET 对象(包括,例如,DACL 和SACL 的两个RawAcl 对象)。此托管表示与非托管SecurityDescriptor 的绝对形式或自相关形式没有直接关系。

RawSecurityDescriptor 类提供与托管表示的转换,一种转换为文本 SDDL 表示(与您的问题无关),另一种转换为它所谓的“BinaryForm”,它对应于 Win32 自相关结构,将 SD 表示为连续的字节数组。

您的托管代码示例将ctor 用于RawSecurityDescriptor,它将存储在注册表中的自相关字节数组转换为托管表示。然后使用 .NET 代码对托管表示进行更改,最后调用 GetBinaryForm 方法将修改后的 SD 转换回自相关的非托管形式以存储在注册表中。因此托管代码永远不需要关注任何绝对的 SD 结构。

非托管代码确实需要进行每种方式的转换,因为调用以更改 SD 的某些 Win32 API 需要绝对形式。

【讨论】:

以上是关于C#,初学琼林(01)——绝对值(Absolute Value)计算的源代码进化过程及编程的基本范式的主要内容,如果未能解决你的问题,请参考以下文章

C# ASP.NET中的Label怎么实现绝对定位?

案例3,Absolute:绝对定位

absolute绝对定位的非绝对定位用法

HTML中相对定位和绝对定位(absolute,relative)

子元素绝对定位absolute后,自动撑开宽度

绝对中位差Median Absolute Deviation