自定义C# 8.0 Range功能
需求
想让string支持索引为负数。
采用C#中的扩展方法进行实现。
public static class ObjectExtension
{
public static string Span(this string val, int index)
{
if (null == val)
{
return val;
}
int len = val.Length;
// when len > 0 index must be less than val's length.
if ((len > 0 && index >= len) || Math.Abs(index) > len)
{
throw new IndexOutOfRangeException();
}
string result = index >= 0 ? val[index].ToString() : val[len + index].ToString();
return result;
}
}
上述代码只是在字符串中获取按照索引读取某个字符,试想一下,是否可以截取一串字符,同样可是支持负数的呢?
在C# 8.0,引入了Range对象,语法 Raange range=1..4;这样方式获取,从索引为 1到索引为 4但是 4不能包含,也就是读取3个字符。如果想要用负数表示: Range range=1..^4;用 ^表示负数,这个 range表示从索引 1开始到倒数第四个字符结束。
例如:
string str = "abcedfghijklmnopqrstuvwsyz";
Range range = 1..^4;
string result = str[range];
Console.WriteLine(result);
// result : bcedfghijklmnopqrstuv
满足上面的语法,需要将 IDE升级 Visual Studio 2019,很多公司或者很多项目组还在使用旧的 Visual Studio IDE,更有甚者,可能还在使用 Visual Studio 2005,想使用高级语法糖,只能望而却步。如果也想使用类似这样的高级语法呢?答案是肯定可行的,按照上面的扩展,写一个重载方法。
// define Range object
public struct Range
{
private int startIndex;
private int endIndex;
private bool isNotNull;
public Range(int startIndex, int endIndex, bool isValidate = true)
{
if(isValidate && startIndex > endIndex)
{
throw new IndexOutOfRangeException("startIndex must be equal or less than endIndex.");
}
this.startIndex = startIndex;
this.endIndex = endIndex;
this.isNotNull = true;
}
public bool IsNull
{
get
{
return !this.isNotNull;
}
}
internal void CheckNull()
{
if(this.IsNull)
{
throw new Exception("this object is null");
}
}
public int StartIndex
{
get
{
CheckNull();
return this.startIndex;
}
}
public int EndIndex
{
get
{
CheckNull();
return this.endIndex;
}
}
public int Count
{
get
{
if(IsNull)
{
return 0;
}
return this.endIndex - this.startIndex;
}
}
public static implicit operator Range(string input)
{
if(string.IsNullOrEmpty(input))
{
return default(Range);
}
Regex re = new Regex(@"^(\^?)\d+\.\.(\^?)\d+$");
Regex re3 = new Regex(@"^\.\.(\^?)\d+$");
Regex re2 = new Regex(@"^(\^?)\d+\.\.$");
Match match = null;
int matchFlag = 0;
if (re.IsMatch(input))
{
matchFlag = 1;
match = re.Match(input);
}
else if (re2.IsMatch(input))
{
matchFlag = 2;
match = re2.Match(input);
}
else if (re3.IsMatch(input))
{
matchFlag = 3;
match = re3.Match(input);
}
// match fails
if (0 == matchFlag)
{
return default(Range);
}
string[] strs = match.Value.Split("..");
int startIndex, endIndex;
int.TryParse(strs[0].Replace("^", "-"), out startIndex);
int.TryParse(strs[1].Replace("^", "-"), out endIndex);
if(2 == matchFlag)
{
endIndex = int.MaxValue;
}else if(3 == matchFlag)
{
startIndex = 0;
}
return new Range(startIndex, endIndex, false);
}
}
添加对string的扩展方法
public static class ObjectExtension
{
public static string Span(this string val, string input)
{
if(string.IsNullOrEmpty(val) || string.IsNullOrEmpty(input))
{
return val;
}
// implicit convert to Range.
Range range = input;
int len = val.Length;
int startIndex = range.StartIndex < 0 ? len + range.StartIndex : range.StartIndex;
int endIndex = range.EndIndex < 0 ? len + range.EndIndex : range.EndIndex;
if(range.EndIndex == int.MaxValue)
{
endIndex = len;
}
range = new Range(startIndex, endIndex);
return val.Span(range);
}
public static string Span(this string val, Range range)
{
if(string.IsNullOrEmpty(val) || range.IsNull)
{
return val;
}
return val.Substring(range.StartIndex, range.Count);
}
}


浙公网安备 33010602011771号