If-else一时爽,代码维护火葬场。或者if-else的套娃全都令人崩溃,如何减少if-else的使用呢?在cpp中,可以使用map+lambda的方法进行,而在C#中,switch提供了更强的功能,比C++酷多了:)
C中Map其实就是其他数据结构中的字典,在C里面如果一些内容不能使用switch的话,则可以使用Map+lambda的方法:
首先看一下cpp关于switch的文档,截止到C++17标准,switch仍只支持几种简单的类型,支持类型为整形,枚举以及可以隐式转换成整形的类型,那么很明显std::string类型是不支持switch的,那么如果相对输入string的不同做一些不同的事情,那么就可以使用Map+lambda进行操作。
Any expression of integral or enumeration type, or of a class type contextually implicitly convertible to an integral or enumeration type, or a declaration of a single non-array variable of such type with a brace-or-equals initializer.
假设现在我想要模拟一些终端命令,那么我要怎么实现?首先一个循环用于循环侦听输入,然后根据输入的消息进行处理。那么不同情况的输入对应情况要怎么写的?if-else可以使用,但说实话写多了就不清晰,可以考虑使用map+lambda进行操作:
#include<iostream>
#include"FileSystem.h"
#include<sstream>
#include<functional>
#include<map>
using namespace std;
int main() {
//自定义的类,定义了一系列的操作
FileSystem f{};
string str;
vector<string> vec;
map<string, function<void(vector<string>)>> map;
//emplace直接调用构造函数添加,括号内为引用捕获以便使用自定义对象f
map.emplace("cd", [&f](vector<string> vec)->void {f.MoveIn(vec[0]); });
map.emplace("ls", [&f](vector<string> vec)->void {f.ShowDetails(); });
map.emplace("rm-fl", [&f](vector<string> vec)->void {f.DeleteFile(vec[0]); });
map.emplace("rm-fo", [&f](vector<string> vec)->void {f.DeleteFolder(vec[0]); });
map.emplace("rename", [&f](vector<string> vec)->void {f.ChangeName(vec[0],vec[1]); });
map.emplace("ls-a", [&f](vector<string> vec)->void {f.ShowAll(); });
map.emplace("mkdir", [&f](vector<string> vec)->void {f.NewFolder(vec[0]); });
map.emplace("newfile", [&f](vector<string> vec)->void {f.NewFile(vec[0]); });
f.CurrentPath();
while (getline(cin,str,'\n'))
{
vec.clear();
try {
stringstream ss(str);
while (getline(ss, str, ' '))
{
vec.push_back(str);
}
auto choice = vec[0];
vec.erase(vec.begin());
map[choice](vec);
f.CurrentPath();
}
catch (exception) {
cout << "Invaild input!" << endl;
f.CurrentPath();
}
}
}
当我们看向C#的switch的时候,情况就好起来了,C#的switch提供的功能极其强大,当然很多功能离不开反射(C认为你不需要为你可能用不到的东西买单,所以不提供元数据的C自然不提供反射功能),给予了更强的空间与方法。详细了解C#8.0的switch.
当你使用C#完成这项任务的时候,使用dictionary+action就并不是一个明智的选择了,switch为我们提供了更强大的功能,你只需要为特定的string实现自己的逻辑即可。
这里就是switch的强大之处了,拥有非常高的自由度。不仅可以在里面添加一些筛选条件,也可以对类型进行一些筛选。下面的实例代码是微软文档提供的:
using System;
public abstract class Shape
{
public abstract double Area { get; }
public abstract double Circumference { get; }
}
public class Rectangle : Shape
{
public Rectangle(double length, double width)
{
Length = length;
Width = width;
}
public double Length { get; set; }
public double Width { get; set; }
public override double Area
{
get { return Math.Round(Length * Width,2); }
}
public override double Circumference
{
get { return (Length + Width) * 2; }
}
}
public class Square : Rectangle
{
public Square(double side) : base(side, side)
{
Side = side;
}
public double Side { get; set; }
}
public class Circle : Shape
{
public Circle(double radius)
{
Radius = radius;
}
public double Radius { get; set; }
public override double Circumference
{
get { return 2 * Math.PI * Radius; }
}
public override double Area
{
get { return Math.PI * Math.Pow(Radius, 2); }
}
}
public class Example
{
public static void Main()
{
Shape sh = null;
Shape[] shapes = { new Square(10), new Rectangle(5, 7),
sh, new Square(0), new Rectangle(8, 8),
new Circle(3) };
foreach (var shape in shapes)
ShowShapeInfo(shape);
}
private static void ShowShapeInfo(Shape sh)
{
switch (sh)
{
// Note that this code never evaluates to true.
case Shape shape when shape == null:
Console.WriteLine($"An uninitialized shape (shape == null)");
break;
case null:
Console.WriteLine($"An uninitialized shape");
break;
case Shape shape when sh.Area == 0:
Console.WriteLine($"The shape: {sh.GetType().Name} with no dimensions");
break;
case Square sq when sh.Area > 0:
Console.WriteLine("Information about square:");
Console.WriteLine($" Length of a side: {sq.Side}");
Console.WriteLine($" Area: {sq.Area}");
break;
case Rectangle r when r.Length == r.Width && r.Area > 0:
Console.WriteLine("Information about square rectangle:");
Console.WriteLine($" Length of a side: {r.Length}");
Console.WriteLine($" Area: {r.Area}");
break;
case Rectangle r when sh.Area > 0:
Console.WriteLine("Information about rectangle:");
Console.WriteLine($" Dimensions: {r.Length} x {r.Width}");
Console.WriteLine($" Area: {r.Area}");
break;
case Shape shape when sh != null:
Console.WriteLine($"A {sh.GetType().Name} shape");
break;
default:
Console.WriteLine($"The {nameof(sh)} variable does not represent a Shape.");
break;
}
}
}
// The example displays the following output:
// Information about square:
// Length of a side: 10
// Area: 100
// Information about rectangle:
// Dimensions: 5 x 7
// Area: 35
// An uninitialized shape
// The shape: Square with no dimensions
// Information about square rectangle:
// Length of a side: 8
// Area: 64
// A Circle shape
本文章使用limfx的vsocde插件快速发布