Last active
April 21, 2019 09:49
-
-
Save dasannikov/c68cb57adf09c125db2edf2fe82d7254 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Text; | |
//---------------------------------------------------------------------------- | |
// Using: | |
// | |
// private UpdateCheckString<int, int> _updateCheck; | |
// ... | |
// if(_updateCheck.IsChanged("Time now: {0}:{1}", DateTime.UtcNow.Minute, DateTime.UtcNow.Second)) | |
// TextObject.text = _updateCheck; | |
// | |
//---------------------------------------------------------------------------- | |
public struct UpdateCheckString<T1> where T1 : IEquatable<T1> { | |
private StringBuilder _sb; | |
private T1 _prevValue; | |
public static implicit operator string(UpdateCheckString<T1> t) { | |
return t._sb != null ? t._sb.ToString() : ""; | |
} | |
public bool IsChanged(string format, T1 value) { | |
// Lazy init or check update | |
if(_sb == null) { | |
_sb = new StringBuilder(20); | |
_prevValue = value; | |
} else if(_prevValue.Equals(value)) { | |
return false; | |
} | |
// Update Text | |
_prevValue = value; | |
_sb.Clear(); | |
_sb.AppendFormat(format, value); | |
return true; | |
} | |
} | |
//---------------------------------------------------------------------------- | |
public struct UpdateCheckString<T1, T2> where T1 : IEquatable<T1> where T2 : IEquatable<T2> { | |
private StringBuilder _sb; | |
private T1 _prevValue1; | |
private T2 _prevValue2; | |
public static implicit operator string(UpdateCheckString<T1, T2> t) { | |
return t._sb != null ? t._sb.ToString() : ""; | |
} | |
public bool IsChanged(string format, T1 value1, T2 value2) { | |
// Lazy init or check update | |
if(_sb == null) { | |
_sb = new StringBuilder(20); | |
_prevValue1 = value1; | |
_prevValue2 = value2; | |
} else if(_prevValue1.Equals(value1) && _prevValue2.Equals(value2)) | |
return false; | |
// Update Text | |
_prevValue1 = value1; | |
_prevValue2 = value2; | |
_sb.Clear(); | |
_sb.AppendFormat(format, value1, value2); | |
return true; | |
} | |
} | |
//---------------------------------------------------------------------------- | |
public struct UpdateCheckString<T1, T2, T3> | |
where T1 : IEquatable<T1> | |
where T2 : IEquatable<T2> | |
where T3 : IEquatable<T3> { | |
private StringBuilder _sb; | |
private T1 _prevValue1; | |
private T2 _prevValue2; | |
private T3 _prevValue3; | |
public static implicit operator string(UpdateCheckString<T1, T2, T3> t) { | |
return t._sb != null ? t._sb.ToString() : ""; | |
} | |
public bool IsChanged(string format, T1 value1, T2 value2, T3 value3) { | |
// Lazy init or check update | |
if(_sb == null) { | |
_sb = new StringBuilder(20); | |
_prevValue1 = value1; | |
_prevValue2 = value2; | |
_prevValue3 = value3; | |
} else if(_prevValue1.Equals(value1) && _prevValue2.Equals(value2) && _prevValue3.Equals(value3)) | |
return false; | |
// Update Text | |
_prevValue1 = value1; | |
_prevValue2 = value2; | |
_prevValue3 = value3; | |
_sb.Clear(); | |
_sb.AppendFormat(format, value1, value2, value3); | |
return true; | |
} | |
} | |
//---------------------------------------------------------------------------- | |
public struct UpdateCheckString<T1, T2, T3, T4> | |
where T1 : IEquatable<T1> | |
where T2 : IEquatable<T2> | |
where T3 : IEquatable<T3> | |
where T4 : IEquatable<T4> { | |
private StringBuilder _sb; | |
private T1 _prevValue1; | |
private T2 _prevValue2; | |
private T3 _prevValue3; | |
private T4 _prevValue4; | |
public static implicit operator string(UpdateCheckString<T1, T2, T3, T4> t) { | |
return t._sb != null ? t._sb.ToString() : ""; | |
} | |
public bool IsChanged(string format, T1 value1, T2 value2, T3 value3, T4 value4) { | |
// Lazy init or check update | |
if(_sb == null) { | |
_sb = new StringBuilder(20); | |
_prevValue1 = value1; | |
_prevValue2 = value2; | |
_prevValue3 = value3; | |
_prevValue4 = value4; | |
} else if(_prevValue1.Equals(value1) && _prevValue2.Equals(value2) && _prevValue3.Equals(value3) && _prevValue4.Equals(value4)) | |
return false; | |
// Update Text | |
_prevValue1 = value1; | |
_prevValue2 = value2; | |
_prevValue3 = value3; | |
_prevValue4 = value4; | |
_sb.Clear(); | |
_sb.AppendFormat(format, value1, value2, value3, value4); | |
return true; | |
} | |
} | |
//---------------------------------------------------------------------------- | |
public struct UpdateCheckString<T1, T2, T3, T4, T5> | |
where T1 : IEquatable<T1> | |
where T2 : IEquatable<T2> | |
where T3 : IEquatable<T3> | |
where T4 : IEquatable<T4> | |
where T5 : IEquatable<T5> { | |
private StringBuilder _sb; | |
private T1 _prevValue1; | |
private T2 _prevValue2; | |
private T3 _prevValue3; | |
private T4 _prevValue4; | |
private T5 _prevValue5; | |
public static implicit operator string(UpdateCheckString<T1, T2, T3, T4, T5> t) { | |
return t._sb != null ? t._sb.ToString() : ""; | |
} | |
public bool IsChanged(string format, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) { | |
// Lazy init or check update | |
if(_sb == null) { | |
_sb = new StringBuilder(20); | |
_prevValue1 = value1; | |
_prevValue2 = value2; | |
_prevValue3 = value3; | |
_prevValue4 = value4; | |
_prevValue5 = value5; | |
} else if(_prevValue1.Equals(value1) && _prevValue2.Equals(value2) && _prevValue3.Equals(value3) && _prevValue4.Equals(value4) && _prevValue5.Equals(value5)) | |
return false; | |
// Update Text | |
_prevValue1 = value1; | |
_prevValue2 = value2; | |
_prevValue3 = value3; | |
_prevValue4 = value4; | |
_prevValue5 = value5; | |
_sb.Clear(); | |
_sb.AppendFormat(format, value1, value2, value3, value4, value5); | |
return true; | |
} | |
} |
Гипотетический пример использования
public class Player {
public int PosX;
public int PosY;
}
public class PlayerView {
void Update1() {
ScreenText = "Position: " + PlayerObject.PosX + ":" + PlayerObject.PosY;
}
void Update2() {
if(UpdateCheck(PlayerObject.PosX, PlayerObject.PosY))
ScreenText = "Position: " + PlayerObject.PosX + ":" + PlayerObject.PosY;
}
void UpdateIdeal() {
UpdateCheck(ScreenText, "Position: ", PlayerObject.PosX, ":", PlayerObject.PosY);
}
}
1й вариант плохой - мы создаем строку каждый раз
2й вариант - уже лучше но неудобен (см. коммент выше)
3й вариант идеальный?
Есть идеи как решить эту задачу лучше? (может быть в принципе нужен другой подход?)
Обновил. Результат вполне приемлем:
- кэшируемые параметры могут быть произвольного типа
- аллокаций практически нет
- код теперь в структурах (не нужно создавать через new)
- работает все очень быстро
- нужно тиражировать код под разное кол-во параметров
Есть пожелания и замечания по улучшению?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ключевая идея: Автоматически проверять изменения в переменных и если они есть обновлять строку
Требования:
Чем плоха первая версия: (сейчас уже не первая :)
В идеале я хотел бы достичь вот такого кода одной строкой (применения) в функции Update
_updateCheck(TextObject.text, "Time now:", DateTime.UtcNow.Minute, " : ", DateTime.UtcNow.Second);
Но что то мне подсказывает что это невозможно (учитывая требования). Сколько я не пробовал - возникает ненужный боксинг на этапе проверки на измение значения переменных.