小编Kam*_*l T的帖子

超越开放原则

我有一个简单的程序,它根据用户提供的鼠标数据绘制几何图形.我有一个处理鼠标跟踪的类(它获取带有鼠标移动历史的List)和一个名为Shape的抽象类.从这个类中我可以得到一些额外的形状,比如Circle,Rectangle等 - 并且每个形状都会覆盖抽象的Draw()函数.

这一切都运行良好,但问题来自我希望用户能够手动切换所需的形状.我得到了鼠标数据,我知道应该绘制什么样的形状.问题是如何使代码"知道"它应该创建哪个对象并将适当的参数传递给构造函数.此时也不可能添加新的Shape衍生物,这是完全错误的.

我好像不想出来像这样的代码:

List<Shape> Shapes = new List<Shape>();
// somwhere later 

if(CurrentShape == "polyline"){
    Shapes.Add(new Polyline(Points)); 
}
else if (CurrentShape == "rectangle"){
    Shapes.Add(new Rectangle(BeginPoint, EndPoint));
}
// and so on.
Run Code Online (Sandbox Code Playgroud)

上面的代码清楚地证明了开放封闭原则.问题是我没有任何好主意如何克服它.主要问题是不同的Shapes具有不同参数的构造函数,这使得它更加麻烦.

我很确定这是一个常见的问题,但我不知道如何克服它.你有什么想法吗?

c# open-closed-principle

7
推荐指数
2
解决办法
761
查看次数

是否可以使用Linq和lambdas而不包含System.Linq命名空间?

前段时间,我一直在研究一个非常扭曲的项目 - 我只能在单个范围内编写代码,然后将其放入C#函数(由另一个模块).

我只能使用之前声明的名称空间(我对它们没有任何影响)并且只能使用我工作的作用域中的变量.因此,我无法更改标题和包含的库.

当我想操作泛型集合时出现问题 - 我既不能使用lambda表达式,也不能使用LINQ - 我根本无法放置using System.Linq;,因为我无法访问文件头.

我只需做一件简单的事情,没有LINQ或lambda就很容易管理.但是,之后我想知道会发生什么,如果我不得不在IEnumerable上使用一些更复杂的操作.从那以后,我的问题出现了:

是否可以在不更改文件头和添加新命名空间的情况下使用LINQ或lambdas?

让我们说我们有一个List<int> _Numbers = new List<int>();.让它充满一些数字.现在我想从中选择所有偶数.

using System.Linq;在报头中,该溶液是显而易见的:

List<int> _NewList = _Numbers.Where(n => n % 2 == 0).ToList();
Run Code Online (Sandbox Code Playgroud)

要么

List<int> _NewList = (from _Number in _Numbers where _Number % 2 == 0 select _Number).ToList();
Run Code Online (Sandbox Code Playgroud)

但是如果不包含LINQ,我该如何实现呢?我的第一个猜测是这样的:

List<int> _NewList = System.Linq. // ??? What to add here?
Run Code Online (Sandbox Code Playgroud)

我知道这个问题很奇特,走这条路是很不寻常的,但我只是很好奇,而且我没有找到关于这个案例的信息.

c# linq lambda

7
推荐指数
1
解决办法
1921
查看次数

从config中加载一些,从configSource加载其他一些

我有一个带<appSettings>标签的配置文件.我希望它们中的一些是常量,并从另一个配置文件加载其中一些.

Web.config文件:

<appSettings>
  <add key="commonKey1" value="commonValue1" />
  <add key="commonKey2" value="commonValue2" />
  <add key="commonKey3" value="commonValue3" />
  <!-- ??? -->
</appSettings>
Run Code Online (Sandbox Code Playgroud)

AdditionalSettings.config

<appSettings>
  <add key="AdditionalKey1" value="AdditionalValue1" />
  <add key="AdditionalKey2" value="AdditionalValue2" />
</appSettings>
Run Code Online (Sandbox Code Playgroud)

结果:Web.config编译后应该像这样:

<appSettings>
  <add key="commonKey1" value="commonValue1" />
  <add key="commonKey2" value="commonValue2" />
  <add key="commonKey3" value="commonValue3" />
  <add key="AdditionalKey1" value="AdditionalValue1" />
  <add key="AdditionalKey2" value="AdditionalValue2" />
</appSettings>
Run Code Online (Sandbox Code Playgroud)

如果所有值都存储在单独的文件中,这很容易:

<appSettings configSource="Settings.config" />
Run Code Online (Sandbox Code Playgroud)

但是我不知道如果基本文件中应该存在某些标签,如何合并两个文件,并且只应从单独的标签加载其他标签.

我也试过了

<appSettings configSource="Settings.config">
  <add key="commonKey1" value="commonValue1" />
  <add key="commonKey2" value="commonValue2" />
  ... etc
Run Code Online (Sandbox Code Playgroud)

但它不会起作用: A section using 'configSource' …

c# asp.net-mvc web-config

7
推荐指数
1
解决办法
2717
查看次数

为什么.Net Native以相反的顺序编译循环?

我正在研究.Net Native编译器执行的优化技术.我创建了一个示例循环:

        for (int i = 0; i < 100; i++)
        {
            Function();
        }
Run Code Online (Sandbox Code Playgroud)

我用Native编译了它.然后我.dll用IDA里面的机器代码反汇编了结果文件.结果,我有:

在此输入图像描述

(我删除了一些不必要的行,所以不要担心地址行不一致)

我明白这add esi, 0FFFFFFFFh意味着subtract one from esi and alter Zero Flag if needed,所以如果还没有达到零,我们可以跳到开头.

我不明白的是为什么编译器重新循环?

我得出结论

LOOP:
add esi, 0FFFFFFFFh
jnz LOOP
Run Code Online (Sandbox Code Playgroud)

比例如更快

LOOP:
inc esi
cmp esi, 064h
jl LOOP
Run Code Online (Sandbox Code Playgroud)

但是真的是因为这个并且速度差异真的很重要吗?

c# x86 assembly micro-optimization .net-native

6
推荐指数
1
解决办法
160
查看次数

为什么Console.WriteLine()使用ecx寄存器,尽管eax和ebx是免费的,但仍会发生事件?

我正在对CIL优化技术进行一些研究。我创建了以下简单代码:

int Function() { return 10; }
// (...)
int Number = Function();
Console.WriteLine(Number);
Run Code Online (Sandbox Code Playgroud)

当我在反汇编窗口中观看此代码时,会看到类似以下内容的内容:

00252DB0  mov ecx,0Ah  
00252DB5  call 63A96648  
00252DBA  ret  
Run Code Online (Sandbox Code Playgroud)

我知道它将10放入ecx,然后用作 函数63A96648指针WriteLine(),但是我不确定为什么要使用ecx寄存器。

我始终认为,ecx主要用于循环计数器(当然,这就是所谓的“计数寄存器”的一个原因......),我不知道为什么它用于WriteLine()功能,即使eaxebx是免费的。即使编写更复杂的函数,最后也总是ecxWriteLine()函数之前。

我试图在Internet上找到任何有关它的东西,甚至从我的大学图书馆里找到几本书,但什么都没找到。是ecx更快还是完全没有理由使用它?

我完全意识到我不应该对此太在乎(因为只要有效,我就可以了),但是过去几天一直在困扰我,我希望有人能告诉我为什么使用该寄存器。

.net c# assembly

5
推荐指数
1
解决办法
90
查看次数

为什么VS2015允许.Net 4.5.2应用程序使用C#6.0函数?

我在Visual Studio 2015中遇到了一个奇怪的行为.我正在编写一个针对4.5.2 .Net Framework的应用程序:

.Net版

然后在应用程序中,我尝试使用在C#6.0(来自.Net 6.0)中实现的一些东西:

int number = 456;
var name = nameof(number);
string str = $"Time = {DateTime.Now}";
Run Code Online (Sandbox Code Playgroud)

我很确定nameof使用的字符串格式$仅在.Net 4.6中可用,但我仍然可以编译此代码 - 尽管我的目标是4.5.2.

我在Visual Studio 2013中运行相同的代码,也针对4.5.2版本,但这次我无法编译代码(nameof未找到).

怎么可能,VS2015允许我编译目标.Net Framework版本中不应该允许的代码?

我在黑暗中拍摄的是VS2015能够将C#6.0代码计算到CIL中,这仍然与以前的版本兼容,但我不确定它是否是正确的猜测.

.net c# roslyn c#-6.0

4
推荐指数
1
解决办法
2445
查看次数

无法将HTMLImageElement转换为字符串?

我正在使用javascript来嵌入嵌套在某些中的img元素<div>.之后我想将这些图像添加到字符串变量中.

我写道:

var SomeVariable="";
$("myDivId img").each(function(){
  console.log(this);
  SomeVariable += this;
});
console.log(SomeVariable);
Run Code Online (Sandbox Code Playgroud)

console.log在使用.each功能,它显示是这样的:

<img (some elements)>,这正是我想要的.

当我最后使用console.log时,要写出整个价值,它说:

[object HTMLImageElement][object HTMLImageElement]
Run Code Online (Sandbox Code Playgroud)

我尝试使用一些转换,但我真的不知道如何实现它.

javascript

2
推荐指数
1
解决办法
4882
查看次数