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 搭建合适的编程环境
点击下面的链接学习(动画演示,步步未惊心!):
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
命名空间中的类(如RawSecurityDescriptor
、RawAcl
等)提供了相应 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)计算的源代码进化过程及编程的基本范式的主要内容,如果未能解决你的问题,请参考以下文章