更新:这不再是来自C#6的问题,它引入了
nameof运营商来解决这些问题(参见MSDN).注意:有关此问题的一般化以及一些答案,请参阅" 在运行时通过lambda表达式获取局部变量(和参数)的名称 ".
我喜欢使用lambda表达式创建INotifyPropertyChanged接口的重构安全实现的想法,使用类似于Eric De Carufel提供的代码.
我正在尝试实现类似的东西ArgumentException,以重构安全的方式为(或其派生类)提供参数名称.
我已经定义了以下实用程序方法来执行null检查:
public static void CheckNotNull<T>(Expression<Func<T>> parameterAccessExpression)
{
Func<T> parameterAccess = parameterAccessExpression.Compile();
T parameterValue = parameterAccess();
CheckNotNull(parameterValue, parameterAccessExpression);
}
public static void CheckNotNull<T>(T parameterValue,
Expression<Func<T>> parameterAccessExpression)
{
if (parameterValue == null)
{
Expression bodyExpression = parameterAccessExpression.Body;
MemberExpression memberExpression = bodyExpression as MemberExpression;
string parameterName = memberExpression.Member.Name;
throw new ArgumentNullException(parameterName);
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以使用以下语法以重构安全的方式执行参数验证:
CheckNotNull(() => arg); // most concise
CheckNotNull(arg, …Run Code Online (Sandbox Code Playgroud) 有没有办法使用文化敏感的相等比较从字符串中获取匹配的子字符串?例如,EN-US区域性下,æ和ae被视为相等."Encyclopædia".IndexOf("aed")评估8,表示匹配; 但是,有没有办法提取匹配的子字符串æd,这不涉及迭代源字符串?注意,所寻找和匹配的子串的长度可以相差几个字符.
假设我正在设计一个包装内部集合的线程安全类:
public class ThreadSafeQueue<T>
{
private readonly Queue<T> _queue = new Queue<T>();
public void Enqueue(T item)
{
lock (_queue)
{
_queue.Enqueue(item);
}
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
基于我的另一个问题,上面的实现是错误的,因为当它的初始化与其使用同时执行时可能会出现种族危险:
ThreadSafeQueue<int> tsqueue = null;
Parallel.Invoke(
() => tsqueue = new ThreadSafeQueue<int>(),
() => tsqueue?.Enqueue(5));
Run Code Online (Sandbox Code Playgroud)
上面的代码是可接受的非确定性的:该项目可能会或可能不会入队.但是,在当前的实现中,它也被破坏了,并且可能引起不可预测的行为,例如抛出IndexOutOfRangeException,NullReferenceException多次将相同的项目入队,或者陷入无限循环.这是因为Enqueue调用可能在将新实例分配给局部变量tsqueue之后但在内部_queue字段的初始化完成(或似乎完成)之前运行.
Per Jon Skeet:
在将对新对象的引用分配给实例之前,Java内存模型不能确保构造函数完成.Java内存模型经历了1.5版的重新加工,但是在没有volatile变量的情况下,双重检查锁定仍然被破坏(如在C#中).
可以通过向构造函数添加内存屏障来解决此种族危险:
public ThreadSafeQueue()
{
Thread.MemoryBarrier();
}
Run Code Online (Sandbox Code Playgroud)
同样,通过使字段变化可以更简洁地解决:
private volatile readonly Queue<T> _queue = new …Run Code Online (Sandbox Code Playgroud) 我正在使用ADO.NET从SQL Server将一些数据投影为XML。我的某些数据包含在XML中无效的字符,例如CHAR(7)(称为BEL)。
SELECT 'This is BEL: ' + CHAR(7) AS A FOR XML RAW
Run Code Online (Sandbox Code Playgroud)
<row A="This is BEL: " />
Run Code Online (Sandbox Code Playgroud)
但是,即使编码形式在XML 1.0下也是无效的,并且会在XML解析器中引起错误:
var doc = XDocument.Parse("<row A=\"This is BEL: \" />");
// XmlException: ' ', hexadecimal value 0x07, is an invalid character. Line 1, position 25.
Run Code Online (Sandbox Code Playgroud)
我想用Unicode替换字符替换所有这些无效的数字引用'?'。我知道如何对未编码的XML执行此操作:
string str = "<row A=\"This is BEL: \u0007\" />";
if (str.Any(c => !XmlConvert.IsXmlChar(c)))
str = new string(str.Select(c => XmlConvert.IsXmlChar(c) ? c …Run Code Online (Sandbox Code Playgroud) 大多数来源,包括Oracle自己的Top-N Queries文章,都提供了类似于以下内容的语法来执行Top-N查询:
SELECT val
FROM (
SELECT val
FROM rownum_order_test
ORDER BY val DESC
)
WHERE ROWNUM <= 5;
Run Code Online (Sandbox Code Playgroud)
这保证给出前5个值; 但是,它是否保证以正确的顺序给予它们?这个问题引用维基百科,但另有说明:
尽管某些数据库系统允许在子选择或视图定义中指定ORDER BY子句,但其中的存在无效.
这是否意味着上述代码不保证任何订购,并且需要额外的ORDER BY,或者是特殊情况?
SELECT val
FROM (
SELECT val
FROM rownum_order_test
ORDER BY val DESC
)
WHERE ROWNUM <= 5
ORDER BY val DESC; -- Is this line necessary?
Run Code Online (Sandbox Code Playgroud)
编辑:假设外部查询将直接执行(不嵌套在另一个查询中).我提出这个问题是因为感觉像是一个明显的遗漏,没有任何消息来源(包括甲骨文)不愿意提到它的需要ORDER BY,尽管从这样的前n个查询中可以直观地预期排序.
执行Volatile.Read只是在读取后插入一个内存屏障:
public static int Read(ref int location)
{
var value = location;
Thread.MemoryBarrier();
return value;
}
Run Code Online (Sandbox Code Playgroud)
因此,使用这样的方法......
return Volatile.Read(ref _a) + Volatile.Read(ref _b);
Run Code Online (Sandbox Code Playgroud)
......相当于:
var a = _a;
Thread.MemoryBarrier();
var b = _b;
Thread.MemoryBarrier();
return a + b;
Run Code Online (Sandbox Code Playgroud)
鉴于上述情况,如果参数不是ref?,结果行为是否相同?
public static int Read(int value)
{
Thread.MemoryBarrier();
return value;
}
Run Code Online (Sandbox Code Playgroud)
我猜这个ref参数只是用来阻止程序员传递除变量以外的东西,比如Volatile.Read(2 + 3).任何人都可以看到ref传递变量的任何其他原因吗?
我有一个大磁盘文件(大约8 GB),包含我需要读取的几百万条记录,在内存中处理,并写回另一个文件.所有记录都具有固定长度(例如,100字节).
我正在考虑将我的进程并行化以在多个线程(通常是4-8)上运行,每个线程将(唯一地)分配要处理的文件的特定部分(例如,1 GB块).由于每个线程都会限制其读取和写入已分配的文件部分,因此我的代码不存在种族危险的风险.
我是否允许初始化多个线程,每个线程都有自己的线程,FileStream用于在不锁定的情况下读取/写入同一文件,而不会有损坏的风险?假设目标文件已提前扩展到其完整大小(使用FileStream.SetLength),并且FileShare在打开每个目标文件时指定了相应的标志FileStream.
另外,如果多个线程同时访问同一个文件,是否会因缓冲丢失而导致速度降低?我担心FileStream该类的MSDN文档中的"检测流位置更改"部分,其中指出:
当
FileStream对象的句柄没有独占保留时,另一个线程可以同时访问文件句柄并更改与文件句柄关联的操作系统文件指针的位置.[...]如果在对
Read方法的调用中检测到句柄位置的意外更改,.NET Framework将丢弃缓冲区的内容并再次从文件中读取流.这可能会影响性能,具体取决于文件的大小以及可能影响文件流位置的任何其他进程.
这适用于我的情况,还是由FileStream实例创建的文件句柄是独立且独立的,即使访问同一个文件?
想象一下,我有一个非规范化的表,如下所示:
CREATE TABLE Persons
(
Id int identity primary key,
FirstName nvarchar(100),
CountryName nvarchar(100)
)
INSERT INTO Persons
VALUES ('Mark', 'Germany'),
('Chris', 'France'),
('Grace', 'Italy'),
('Antonio', 'Italy'),
('Francis', 'France'),
('Amanda', 'Italy');
Run Code Online (Sandbox Code Playgroud)
我需要构建一个返回每个人姓名的查询,以及他们所在国家/地区的唯一ID.ID不一定必须是连续的; 更重要的是,他们并没有必须在任何顺序.实现这一目标的最有效方法是什么?
最简单的解决方案似乎是DENSE_RANK:
SELECT FirstName,
CountryName,
DENSE_RANK() OVER (ORDER BY CountryName) AS CountryId
FROM Persons
-- FirstName CountryName CountryId
-- Chris France 1
-- Francis France 1
-- Mark Germany 2
-- Amanda Italy 3
-- Grace Italy 3
-- Antonio Italy 3
Run Code Online (Sandbox Code Playgroud)
然而,这在我的CountryName …
我想将异步操作委托转换为返回指定值的异步函数委托.我想出了一个扩展方法:
public static Func<Task<TResult>> Return<TResult>(this Func<Task> asyncAction, TResult result)
{
ArgumentValidate.NotNull(asyncAction, nameof(asyncAction));
return async () =>
{
await asyncAction();
return result;
};
}
Run Code Online (Sandbox Code Playgroud)
但是,我的扩展方法是错误的,因为从操作委托同步传递的异常现在从函数委托异步传递.具体来说:
Func<Task> asyncAction = () => { throw new InvalidOperationException(); };
var asyncFunc = asyncAction.Return(42);
var task = asyncFunc(); // exception should be thrown here
await task; // but instead gets thrown here
Run Code Online (Sandbox Code Playgroud)
有没有办法以同步异常继续同步传递的方式创建此包装器?是ContinueWith要走的路?
更新:同步抛出异常的异步操作的具体示例:
public static Task WriteAllBytesAsync(string filePath, byte[] bytes)
{
if (filePath == null)
throw new ArgumentNullException(filePath, nameof(filePath));
if (bytes == …Run Code Online (Sandbox Code Playgroud) 我确定之前我看到过这个方法,因为一年前我问过:KeyValuePair<> struct 中的 Deconstruct 方法的目的是什么?
但现在我根本找不到它,或者任何关于它被移除的痕迹,任何问题,什么都没有。
编译器同意:
var s = new KeyValuePair<int, int>(1, 3);
var (x, y) = s;
Run Code Online (Sandbox Code Playgroud)
错误 CS1061“KeyValuePair”不包含“Deconstruct”的定义,并且找不到接受“KeyValuePair”类型的第一个参数的可访问扩展方法“Deconstruct”(您是否缺少 using 指令或程序集引用?
错误 CS8129 找不到适合类型“KeyValuePair”的“解构”实例或扩展方法,具有 2 个输出参数和一个 void 返回类型。
这是怎么回事?
以下代码适用于常规类型:
public static string GetPropertyName(this Expression<Func<object>> property)
{
MemberExpression member = property.Body as MemberExpression;
PropertyInfo propInfo = member.Member as PropertyInfo;
return propInfo.Name;
}
GetPropertyName(() => obj.MyProperty); //Returns "MyProperty"
Run Code Online (Sandbox Code Playgroud)
但是,如果您将匿名类型的属性传递给它,它会引发空引用异常,因为表达式主体是 UnaryExpression 而不是 MemberExpression。
如何使此函数对匿名类型正常工作?
.net ×10
c# ×10
lambda ×2
sql ×2
volatile ×2
.net-4.0 ×1
async-await ×1
asynchronous ×1
c#-7.0 ×1
concurrency ×1
dense-rank ×1
expression ×1
file-io ×1
key-value ×1
oracle ×1
ref ×1
row-number ×1
sql-server ×1
string ×1
t-sql ×1
task ×1
xml ×1