# 自定义结构体实现操作符
public struct Grid2D {
// 必须是静态
public static bool operator == (Grid2D a, Grid2D b) {
return (a.m_x == b.m_x) && (a.m_y == b._my);
}
// opertator == 和 operator != 必须成对出现,否则会语法错误
public static bool operator != (Grid2D a, Grid2D b) {
return a.m_x != b.m_x || a.m_x != b.m_x;
}
public int m_x;
public int m_y;
}
#扩展实现
public interfce IProcessQueue {
void PushActionProcess(ActionProcess process);
}
// 类必须要static
public static clas ProcessPushHelper {
// 函数必须要static
public static void PushWaitProcess(this IProcessQueue processQueue, BattleActorChar owner) {
// ...
}
}
# 条件引入头文件
#if XXX_ThreadSafe
using System.Threading
#endif
vs2017 写入条件编译符号
#List元素父子之间的cast
public class FatherNode { }
public class ChildNode : FatherNode { }
var result = new List<FatherNode>(); // 但是其实元素是 ChildNode
...
// 转换如下, 假设用于返回转换,返回为 List<ChildNode>
return result.Cast<ChildNode>().ToList
nodes.AddRange(m_grids.Cast<DJNode>().ToList().FindAll(node => node != null));
# 查看IEnumerable是否为空
# IEnumerable<XXX> path;
if (!path.Any()) { return false; } // 判断是否有元素
# 在基类和具体类之间的跳转
public abstract class Father {
protected Father(int id) {
m_id = id;
}
public int m_father;
public readonly int m_id;
}
public class Child1 : Father {
public Child1(int id) : base(id) {}
public int m_child1;
}
public class ChildOnly : Father {
public ChildOnly(int id) : base(id) {}
public int m_childOnly;
}
public static class XXXFactory {
public static Father CreateXXX(XXXType type) {
int seqId = AllocId();
Father f = null;
switch(type) {
case Child1:
f = new Child1(seqId);
break;
case ChildOnly:
f = m_childOnly;
...
default:
// 参数越界
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
return f;
}
// 重点,意会一下 (模板函数)
public static T int CreateXXX<T>(XXXType type)
where T : Father {
return CreateXXX(type) as T;
}
protected static int AllocId() {
return Interlocked.Increment(ref m_seqId);
}
protected static readonly ChildOnly m_childOnly = new ChildOnly(-1);
protected static int m_seqId;
}
# 静态函数转接到实例化类直接调用
public interface IXXXQueue {
void PushXXX(XXX xxx);
}
public class XXXRealize : IXXXQueue {
}
public static class XXXPushHelper {
public static void PushYYY(this IXXXQueue xxxQueue, XXX xxx) {
var yyy = XXXFactory.CreateXXX<YYY>(xxxType);
yyy.m_owner = owner;
// 转接
yyyQueue.PushXXX(xxx);
}
}
// 外面使用
using System;
namespace CShapr {
class Program {
static void Main() {
IXXXQueue xxx = new XXXRealize();
// 意会一下
xxx.PushYYY();
}
}
}
#new时初始化
var xxx = new XXX {
m_x = 100,
m_y = 1000
};
// 带数组情况
public class BattlePipeEvent
{
/// <summary>
/// 事件类型
/// </summary>
public BattlePipeEventType m_type;
/// <summary>
/// 参数
/// </summary>
public object[] m_params = new object[CommonDefine.PipeEventParamNum];
}
var pipeEvent2 = new BattlePipeEvent
{
m_type = BattlePipeEventType.BattlePipeEventType_BattleTurnStart,
m_params = {[0] = turnCount}
};
# Debug.Assert
Debug.Assert(xxx != null, nameof(xxx) + " != null");
# 模板类
public interface IXXX {
string KeyGet();
}
public class XXXTargetInfo : IXXX {
}
public class XXXRankingList<T> where T : class, IXXX {
}
public class XXXBase : XXXRankingList<XXXTargetInfo> {
}
# 接口成员可以用 event
public interface IXXX {
event Action<xxx> EventOnXXX;
}
public class XXX : IXXX {
public event Action<xxx> EventOnXXX;
}
#nameof
打印变量在代码里的字段名
namespace CSharp {
class XXX {
public string m_name;
public int m_age;
}
class Program {
static void Main() {
XXX x = new XXX();
Console.WriteLine(nameof(x.m_name)); // 打印 m_name
Console.WriteLine(nameof(x.m_age)); // 打印 m_age
}
}
}
#基类的abstract函数,如果子类是一个abstract类可以不实现,留给孙子去实现
public abstract class A {
public abstract Init();
}
public abstract class AA {
// 可以不实现 Init
}
public class AAA {
// 必须要实现Init
public override Init() {
}
}
# 显示实现接口前面不需要加public
public interface IA {
void xxx();
}
public class A : IA {
// 显示实现前面不需要加public
void IA.xxx() {
}
}
# List的Foreach
m_listenerList.ForEach(listener => {
listener.OnActionAction(processList);
});
# 抛出异常
throw new Exception($"TickFightCmd Actor is null, actorId:{cmd.m_actorId}, battleSceneId:{m_compBasicCtx.ConfigDataBattleSceneInfoGet().ID}");
# 非空转化
if (!(actor is BattleActorTurnActionSrc turnActor))
{
throw new Exception($"TickFightCmd Actor Is Not BattleActorTurnActionSrc, ActorId:{cmd.m_actorId}, BattleSceneId:{m_compBasicCtx.ConfigDataBattleSceneInfoGet().ID}");
}
# 重写new
protected new IBattleActorTacticalUnitCompOwner m_owner;
# 静态无效类,只会new一次的写法
public static Grid2D Null { get; } = new Grid2D(-1, -1);
===等价于
public static Grid2D Null {
get {return _null}
}
private static Grid2D _null = new Grid2D(-1, -1);
#List的TrueForAll
if (m_defendWinCondStates.TrueForAll(state => state.m_isMatch) || m_isReachTurnMax)
#三目运算
public void MovePointReset(int? point = null)
{
m_curMovePoint = point ?? MovePointCalc();
}
#List元素批量转换
protected void MoveProcessPush(List<BattleGrid> paths)
{
var process = ProcessFactory.ProcessCreate<ActionProcessMove>(ProcessType.ProcessType_Move);
process.m_owner = (BattleActorBase)m_owner;
process.m_fromLocation = paths.First().LocationGet();
process.m_destLocation = paths.Last().LocationGet();
process.m_grids.AddRange(paths.ConvertAll(battleGrid => battleGrid.LocationGet()));
((BattleActorBase)m_owner).ActionProcessPush(process);
}
#Dictionary插入List
var propertiesForGroupDict = new Dictionary<int, List<T>>();
propertiesForGroupDict.Add(item.PropertyGroup, new List<T> { item });
#定义和初始化一维,二维数组
protected static T[] s_propertiesConfInfoList;
s_propertiesConfInfoList = new T[s_propertiesCount];
protected static T[][] s_propertiesListForGroups;
s_propertiesListForGroups = new T[s_groupMax][];
#写文件
File.WriteAllText(path, JsonConvert.SerializeObject(this, Formatting.Indented));
# IEnumerable 的First和FirstOrDefault
没用满足的元素,First会抛异常,FirstOrDefault不会抛出异常,会default一下,default(类)为空,default(结构体)为结构体
public class Test
{
public int m_i = 10;
}
class Program
{
static void Main()
{
List<Test> list = new List<Test>();
list.Add(new Test
{
m_i = 11
});
list.Add(new Test
{
m_i = 12
});
IEnumerable<Test> enu = list;
// if (enu.First(r => r.m_i == 13) != null) // 抛异常
if (enu.FirstOrDefault(r => r.m_i == 13) != null) // 不会抛异常
{
Console.WriteLine("Get It");
}
Console.ReadLine();
}
}
# default 类和结构体
public class Test
{
public int m_i = 10;
}
public struct Test2
{
public int m_i;
}
var tt = default(Test); // null
var tt2 = default(Test2); // 默认值的结构体实例化对象
# 结构体不是定义成员的时候初始化
public struct Test2
{
public int m_i = 10; // 不对
}
#Select
// 把自己的成员投影成另一种形式
paths = m_compMove.FindPathFromCurLocation(grid.m_battleGrid).Select(b => b.LocationGet());
// IEnumerable<Grid2D> paths,
// IEnumerable<BattleGrid> FindPathFromCurLocation(BattleGrid to);
#Where
// 返回一个子集
// List<BattleActorChar> m_hatredActorChars = new List<BattleActorChar>();
IEnumerable<BattleActorChar> actorChars;
return actorChars.Where(actorChar => m_hatredActorChars.Contains(actorChar)).ToList();
#List RemoveAll
grids.RemoveAll(pair => !pair.Key.IsActorCanStay((BattleActorBase) m_owner));
// List<KeyValuePair<BattleGrid, int>> grids)
# 枚举的反射
[Serializable]
public enum AISkillCastType
{
/// <summary>
/// 奥义
/// </summary>
AISkillCastType_Ougi = 0,
/// <summary>
/// 普通
/// </summary>
AISkillCastType_Normal = 1,
/// <summary>
/// 定向技能-友方
/// </summary>
AISkillCastType_TargetedFriendly = 2,
/// <summary>
/// 定向技能-敌方
/// </summary>
AISkillCastType_TargetedEnemy = 3,
}
AISkillCastTypeCount = Enum.GetValues(typeof(AISkillCastType)).Length;
AISkillCastTypes = (AISkillCastType[])Enum.GetValues(typeof(AISkillCastType));
# string的裁剪 Split
[Serializable]
public enum BtName
{
/// <summary>
/// 战场中不特殊定义
/// </summary>
BtName_Null = 0,
/// <summary>
/// 默认
/// </summary>
BtName_Default = 1,
/// <summary>
/// 治疗者
/// </summary>
BtName_HealActor = 2,
/// <summary>
/// 辅助者
/// </summary>
BtName_Auxiliary = 3,
/// <summary>
/// 防御者
/// </summary>
BtName_Tank = 4,
/// <summary>
/// 远程攻击者
/// </summary>
BtName_Shooter = 5,
/// <summary>
/// 无攻击者
/// </summary>
BtName_UnarmedMan = 6,
}
btName.ToString().Split('_')[1]); // 取下标为1的部分
```
String[] szInfo = stringToken.Split('|');
m_hasAuthID = szInfo[0];
m_platformAuthId = szInfo[1];
m_deviceId = szInfo[2];
m_platformToken = szInfo[3];
m_platformName = szInfo[4];
m_platformId = szInfo[5];
```
# List 元素不一样的比较
// protected List<BattleGridInfo4Move> m_moveReachableGridsCache = new List<BattleGridInfo4Move>();
public struct BattleGridInfo4Move
{
/// <summary>
/// 格子
/// </summary>
public BattleGrid m_battleGrid;
/// <summary>
/// 到达这个格子的cost
/// </summary>
public int m_cost;
/// <summary>
/// 是否可以停留
/// </summary>
public bool m_stayable;
}
// BattleGrid to;
m_moveReachableGridsCache.FindIndex(grid4Info => grid4Info.m_battleGrid == to) < 0
#字符串空的判断
if (!string.IsNullOrEmpty(m_btName))
{
m_fmAIAgent.btsetcurrent(m_btName);
}
#字符串的比较
if (version.ToLower().CompareTo(GameServerBase.Instance.ClientVersion.ToLower()) != 0)
#List是否存在某个元素,不存在则添加
if (!m_actorDeadInfoList.Exists(info => info.m_deadActor == deadActor))
{
m_actorDeadInfoList.Add(actorDeadInfo);
}
protected List<BattleActorDeadInfo> m_actorDeadInfoList = new List<BattleActorDeadInfo>();
#判断IEnumerable是否有元素
IEnumerable<long> candidateCastKeys
candidateCastKeys.Any()
#设置控制台颜色
Console.ForegroundColor = ConsoleColor.DarkMagenta;
Console.WriteLine(text);
Console.ForegroundColor = ConsoleColor.Gray;
#二维数组
int[,] gridsOffset =
{
{ -1, 0},
{1, 0 },
{0, -1 },
{0, 1 }
};
var nearbyGrid = Owner.BattleActorEnvGet().GridGet(new Grid2D(x: m_selectedTarget.LocationGet().m_x + gridsOffset[i, 0], y: m_selectedTarget.LocationGet().m_y + gridsOffset[i, 1]));
#Dictionary 的 Value排序
ConcurrentDictionary<int, ConfigDataWayPointInfo> m_ConfigDataWayPointInfoData = new ConcurrentDictionary<int, ConfigDataWayPointInfo>();
foreach (var wayPoint in m_ConfigDataWayPointInfoData.Values)
{
wayPoint.Events.Sort((lhs, rhs) => lhs.ID > rhs.ID ? 1 : -1);
#可变参数
void SetProcessBattleInfo(BattleType type, params int[] paramList);
#string转int
String[] szTimeStampInfo = szInfo[6].Split('-');
Int32 year = Int32.Parse(szTimeStampInfo[0]);
Int32 month = Int32.Parse(szTimeStampInfo[1]);
Int32 day = Int32.Parse(szTimeStampInfo[2]);
Int32 hour = Int32.Parse(szTimeStampInfo[3]);
Int32 minute = Int32.Parse(szTimeStampInfo[4]);
m_timestamp = new DateTime(year, month, day, hour, minute, 0);
#时间DateTtime
m_timestamp = new DateTime(year, month, day, hour, minute, 0);
m_timestamp.ToString("yyyy-MM-dd-HH-mm")
if(m_timestamp.AddMilliseconds(AuthToken.GetTokenTimeOut()) < DateTime.Now)
#字符串格式化 String.Format
m_plainStringToken = String.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}",
m_hasAuthID, m_platformAuthId, m_deviceId, m_platformToken, m_platformName, m_platformId, m_timestamp.ToString("yyyy-MM-dd-HH-mm"));
m_signature = szInfo[7];
#保护成员访问
protected Int32 m_channelId;
public Int32 ChannelId
{
get { return m_channelId; }
}
#让服务器停止,信号
static void Main(string[] args)
{
var exitEvent = new System.Threading.ManualResetEvent(false);
Console.CancelKeyPress += (sender, eventArgs) =>
{
eventArgs.Cancel = true;
Console.WriteLine("Detect Ctrl-C");
exitEvent.Set();
};
exitEvent.WaitOne();
Console.WriteLine("To End...");
Console.ReadLine();
}
#StopWatch 测试性能
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// ...
stopwatch.Stop();
DebugUtility.Log("----------------BattleReplay end battleSceneId:{0} userId:{1} Elapsed:{2}", record.m_battleSceneId, m_compBasicCtx.GetUserId(), stopwatch.Elapsed);
# sealed 修饰单例
public sealed class LocalBattleHelper
{
public static readonly LocalBattleHelper Instance = new LocalBattleHelper();
/// <summary>
/// 构造函数
/// </summary>
private LocalBattleHelper()
{
}
}
#从文件读写字节
public static byte[] ReadBytes(string fname)
{
if (string.IsNullOrEmpty(fname))
return null;
try
{
return System.IO.File.ReadAllBytes(fname);
}
catch (System.Exception e)
{
Debug.LogError("FileUtility.ReadBytes Error: " + e);
}
return null;
}
public static bool WriteBytes(string fname, byte[] bytes)
{
if (string.IsNullOrEmpty(fname))
return false;
if (bytes == null || bytes.Length <= 0)
return false;
try
{
System.IO.File.WriteAllBytes(fname, bytes);
return true;
}
catch (System.Exception e)
{
Debug.LogError("FileUtility.WriteBytes Error: " + e);
}
return false;
}
#文件读写文本,追加文本
public static string ReadText(string fname)
{
if (string.IsNullOrEmpty(fname))
return string.Empty;
try
{
string txt = System.IO.File.ReadAllText(fname, System.Text.Encoding.UTF8);
if (!string.IsNullOrEmpty(txt))
return txt;
}
catch (System.Exception e)
{
}
return string.Empty;
}
public static bool WriteText(string fname, string txt)
{
if (string.IsNullOrEmpty(fname))
return false;
try
{
System.IO.File.WriteAllText(fname, txt, System.Text.Encoding.UTF8);
return true;
}
catch (System.Exception e)
{
}
return false;
}
public static bool AppendText(string fname, string txt)
{
if (string.IsNullOrEmpty(fname))
return false;
try
{
System.IO.File.AppendAllText(fname, txt, System.Text.Encoding.UTF8);
return true;
}
catch (System.Exception e)
{
}
return false;
}
#protobuf反序列化
public static T DeserializeObject<T>(Byte[] bytes) where T : IMessage<T>, new()
{
MessageParser<T> parser = new MessageParser<T>(() => new T());
return parser.ParseFrom(bytes);
}
#protobuf的序列化
public static byte[] ToByteArray(this IMessage message)
{
ProtoPreconditions.CheckNotNull(message, "message");
byte[] result = new byte[message.CalculateSize()];
CodedOutputStream output = new CodedOutputStream(result);
message.WriteTo(output);
output.CheckNoSpaceLeft();
return result;
}
#带颜色打印
ConsoleForegroundColor.Print(ConsoleColor.Red, "【ExcelCheck】测试错误,请查看日志文件 bin\\Debug\\excelErrorFile.txt");
#List转字符串
var bufIdList = new List<int>();
...
public static string ToString<T>(this IEnumerable<T> obj, char separator)
{
var sb = new StringBuilder();
foreach (var ele in obj)
{
if (ele != null)
{
sb.Append(ele.ToString());
sb.Append(separator);
}
}
return sb.ToString();
}
bufIdList.ToString('|')
#当前时间转字符串
DateTime.Now.ToString("yyyyMMddHHmmss"))
#NewtonSoft.Json.JsonConvert
return JsonConvert.DeserializeObject<BattleSceneInfo>(File.ReadAllText(path));
// 所有的变量跟 json文件里要对其
#List的RemoveAll 带lambda表达式
m_approachList.RemoveAll(actor => m_targetList.Contains(actor));
#空数组
public static readonly ActorBufBase[] EmptyBufs = new ActorBufBase[0];
#Predicate
GetBufListByPredicate(buf => buf.BufConfGet().FuncType == funcType);
IEnumerable<ActorBufBase> GetBufListByPredicate(Predicate<ActorBufBase> predicate)
#可以比较的类
public abstract class ActorBufActiveCondBase : IComparable<ActorBufActiveCondBase>
{
public int CompareTo(ActorBufActiveCondBase dest)
{
return (int)GetActiveCondType() - (int) dest.GetActiveCondType();
}
}