Выполненный php в режиме линта из командной строки для проверки синтаксиса без выполнения:
php -l FILENAME
Высокоуровневые статические анализаторы включают:
, который включают анализаторы Низшего уровня:
PHP_Parser token_get_all Время выполнения анализаторы, которые более полезны для некоторых вещей из-за динамического характера PHPs, включают:
библиотеки документации phpdoc и doxygen выполняют своего рода анализ кода. Doxygen, например, может быть настроен для рендеринга хороших графиков наследования с [1 117] graphviz.
Другая опция xhprof, который подобен xdebug, но легче, делая ее подходящей для рабочих серверов. Инструмент включает основанный на PHP интерфейс.
После прочтения MSDN я был уверен, что лучший пример правильной реализации находится на странице IEquatable.Equals Method . Мое единственное отклонение следующее:
public override bool Equals(Object obj)
{
if (obj == null) return base.Equals(obj);
if (! (obj is Person))
return false; // Instead of throw new InvalidOperationException
else
return Equals(obj as Person);
}
Для тех, кто интересуется отклонением, оно происходит из Object.Equals (Object) страницы MSDN:
Реализации Equals не должны генерировать исключения.
IEquatable
для типа значения Реализация IEquatable
для типа значения немного отличается от ссылочного типа. Предположим, у нас есть архетип «Реализуй-свое-значение-тип», структуру сложного числа.
public struct Complex
{
public double RealPart { get; set; }
public double ImaginaryPart { get; set; }
}
Нашим первым шагом будет реализация IEquatable
и переопределение Object.Equals
и Object.GetHashCode
:
public bool Equals(Complex other)
{
// Complex is a value type, thus we don't have to check for null
// if (other == null) return false;
return (this.RealPart == other.RealPart)
&& (this.ImaginaryPart == other.ImaginaryPart);
}
public override bool Equals(object other)
{
// other could be a reference type, the is operator will return false if null
if (other is Complex)
return this.Equals((Complex)other);
else
return false;
}
public override int GetHashCode()
{
return this.RealPart.GetHashCode() ^ this.ImaginaryPart.GetHashCode();
}
С очень небольшими усилиями у нас есть правильная реализация, за исключением операторов. Добавление операторов - также тривиальный процесс:
public static bool operator ==(Complex term1, Complex term2)
{
return term1.Equals(term2);
}
public static bool operator !=(Complex term1, Complex term2)
{
return !term1.Equals(term2);
}
Проницательный читатель заметит, что нам, вероятно, следует реализовать IEquatable
, поскольку Комплексные
числа могут быть взаимозаменяемыми с базовым типом значения.
public bool Equals(double otherReal)
{
return (this.RealPart == otherReal) && (this.ImaginaryPart == 0.0);
}
public override bool Equals(object other)
{
// other could be a reference type, thus we check for null
if (other == null) return base.Equals(other);
if (other is Complex)
{
return this.Equals((Complex)other);
}
else if (other is double)
{
return this.Equals((double)other);
}
else
{
return false;
}
}
Нам понадобятся четыре оператора, если мы добавим IEquatable
, потому что у вас может быть Complex == double
или double == Complex
(и то же for operator! =
):
public static bool operator ==(Complex term1, double term2)
{
return term1.Equals(term2);
}
public static bool operator ==(double term1, Complex term2)
{
return term2.Equals(term1);
}
public static bool operator !=(Complex term1, double term2)
{
return !term1.Equals(term2);
}
public static bool operator !=(double term1, Complex term2)
{
return !term2.Equals(term1);
}
Вот и все, с минимальными усилиями у нас есть правильная и полезная реализация IEquatable
для типа значения:
public struct Complex : IEquatable<Complex>, IEquatable<double>
{
}
Я нашел еще одну ссылку, это реализация анонимного типа .NET. Для анонимного типа со свойствами int и double я разобрал следующий код C #:
public class f__AnonymousType0
{
// Fields
public int A { get; }
public double B { get; }
// Methods
public override bool Equals(object value)
{
var type = value as f__AnonymousType0;
return (((type != null)
&& EqualityComparer<int>.Default.Equals(this.A, type.A))
&& EqualityComparer<double>.Default.Equals(this.B, type.B));
}
public override int GetHashCode()
{
int num = -1134271262;
num = (-1521134295 * num) + EqualityComparer<int>.Default.GetHashCode(this.A);
return ((-1521134295 * num) + EqualityComparer<double>.Default.GetHashCode(this.B);
}
public override string ToString()
{
StringBuilder builder = new StringBuilder();
builder.Append("{ A = ");
builder.Append(this.A);
builder.Append(", B = ");
builder.Append(this.B);
builder.Append(" }");
return builder.ToString();
}
}