Реализация по умолчанию для Object.GetHashCode ()

Чтобы обрезать все пробелы, как вы его называете, окружая интересную часть изображения, сначала мы узнаем, где останавливается «пробел», а затем мы копируем все внутри этих границ.

//load the image
$img = imagecreatefromjpeg("http://ecx.images-amazon.com/images/I/413XvF0yukL._SL500_AA280_.jpg");

//find the size of the borders
$b_top = 0;
$b_btm = 0;
$b_lft = 0;
$b_rt = 0;

//top
for(; $b_top < imagesy($img); ++$b_top) {
  for($x = 0; $x < imagesx($img); ++$x) {
    if(imagecolorat($img, $x, $b_top) != 0xFFFFFF) {
       break 2; //out of the 'top' loop
    }
  }
}

//bottom
for(; $b_btm < imagesy($img); ++$b_btm) {
  for($x = 0; $x < imagesx($img); ++$x) {
    if(imagecolorat($img, $x, imagesy($img) - $b_btm-1) != 0xFFFFFF) {
       break 2; //out of the 'bottom' loop
    }
  }
}

//left
for(; $b_lft < imagesx($img); ++$b_lft) {
  for($y = 0; $y < imagesy($img); ++$y) {
    if(imagecolorat($img, $b_lft, $y) != 0xFFFFFF) {
       break 2; //out of the 'left' loop
    }
  }
}

//right
for(; $b_rt < imagesx($img); ++$b_rt) {
  for($y = 0; $y < imagesy($img); ++$y) {
    if(imagecolorat($img, imagesx($img) - $b_rt-1, $y) != 0xFFFFFF) {
       break 2; //out of the 'right' loop
    }
  }
}

//copy the contents, excluding the border
$newimg = imagecreatetruecolor(
    imagesx($img)-($b_lft+$b_rt), imagesy($img)-($b_top+$b_btm));

imagecopy($newimg, $img, 0, 0, $b_lft, $b_top, imagesx($newimg), imagesy($newimg));

//finally, output the image
header("Content-Type: image/jpeg");
imagejpeg($newimg);

Мой старый пример, который предполагает идентичную «границу» со всех сторон изображения, просто для уточнения комментариев:)

//load the image
$img = imagecreatefromjpeg("img.jpg");

//find the size of the border.
$border = 0;
while(imagecolorat($img, $border, $border) == 0xFFFFFF) {
  $border++;
}

//copy the contents, excluding the border
//This code assumes that the border is the same size on all sides of the image.
$newimg = imagecreatetruecolor(imagesx($img)-($border*2), imagesy($img)-($border*2));
imagecopy($newimg, $img, 0, 0, $border, $border, imagesx($newimg), imagesy($newimg));

//finally, if you want, overwrite the original image
imagejpeg($newimg, "img.jpg");
151
задан Peter Mortensen 20 April 2012 в 13:41
поделиться

4 ответа

namespace System {
    public class Object {
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern int InternalGetHashCode(object obj);

        public virtual int GetHashCode() {
            return InternalGetHashCode(this);
        }
    }
}

InternalGetHashCode отображается на ObjectNative:: GetHashCode функционируют в CLR, который похож на это:

FCIMPL1(INT32, ObjectNative::GetHashCode, Object* obj) {  
    CONTRACTL  
    {  
        THROWS;  
        DISABLED(GC_NOTRIGGER);  
        INJECT_FAULT(FCThrow(kOutOfMemoryException););  
        MODE_COOPERATIVE;  
        SO_TOLERANT;  
    }  
    CONTRACTL_END;  

    VALIDATEOBJECTREF(obj);  

    DWORD idx = 0;  

    if (obj == 0)  
        return 0;  

    OBJECTREF objRef(obj);  

    HELPER_METHOD_FRAME_BEGIN_RET_1(objRef);        // Set up a frame  

    idx = GetHashCodeEx(OBJECTREFToObject(objRef));  

    HELPER_METHOD_FRAME_END();  

    return idx;  
}  
FCIMPLEND

Полное внедрение GetHashCodeEx является довольно большим, таким образом, легче просто связаться с исходным кодом C++.

86
ответ дан 23 November 2019 в 21:58
поделиться

Для класса значения по умолчанию являются чрезвычайно ссылочным равенством, и это обычно прекрасно. При записи структуры более распространено переопределить равенство (не в последнюю очередь, чтобы не упаковывать), но очень редко, чтобы Вы записали структуру так или иначе!

Когда переопределяющее равенство, у Вас должно всегда быть соответствие Equals() и GetHashCode() (т.е. для двух значений, если Equals() возвращает true, они должны возвратить тот же хэш-код, но обратное не требуется) - и распространено также обеспечить ==/!=операторы, и часто реализовать IEquatable<T> также.

Для генерации хэш-кода распространено использовать учтенную сумму, поскольку это избегает коллизий на парных значениях - например, для основных 2 полевых хешей:

unchecked // disable overflow, for the unlikely possibility that you
{         // are compiling with overflow-checking enabled
    int hash = 27;
    hash = (13 * hash) + field1.GetHashCode();
    hash = (13 * hash) + field2.GetHashCode();
    return hash;
}

Это имеет преимущество что:

  • хеш {1,2} не является тем же как хешем {2,1}
  • хеш {1,1} не является тем же как хешем {2,2}

и т.д. - который может быть распространен просто с помощью невзвешенной суммы или xor (^), и т.д.

84
ответ дан 23 November 2019 в 21:58
поделиться

Документация для GetHashCode в методе для Объекта говорится, что "реализация по умолчанию этого метода не должна использоваться в качестве идентификатора уникального объекта для хеширования целей". и тот для ValueType говорит, "При вызове метода GetHashCode производного типа возвращаемое значение вряд ли подойдет для использования в качестве ключа в хеш-таблице"..

Основные данные вводят как byte, short, int, long, char и string реализуйте хороший метод GetHashCode. Некоторые другие классы и структуры, как Point например, реализация a GetHashCode метод, который может или не может подойти для Ваших определенных потребностей. Просто необходимо испытать его, чтобы видеть, достаточно хорошо ли это.

Документация для каждого класса или структуры может сказать Вам, если это переопределяет реализацию по умолчанию или нет. Если это не переопределяет его, необходимо использовать собственную реализацию. Для любых классов или структур, которые Вы создаете сами, где необходимо использовать GetHashCode метод, необходимо сделать собственную реализацию, которая использует соответствующих участников для вычисления хэш-кода.

7
ответ дан 23 November 2019 в 21:58
поделиться

Вообще говоря, если Вы являетесь переопределяющими, Равняется, Вы хотите переопределить GetHashCode. Причина этого состоит в том, потому что оба используются для сравнения равенства класса/структуры.

Равняется используется при проверке Нечто A, B;

если (== B)

Так как мы знаем, что указатель, вероятно, не будет соответствовать, мы можем сравнить внутренних участников.

Equals(obj o)
{
    if (o == null) return false;
    MyType Foo = o as MyType;
    if (Foo == null) return false;
    if (Foo.Prop1 != this.Prop1) return false;

    return Foo.Prop2 == this.Prop2;
}

GetHashCode обычно используется хеш-таблицами. Хэш-код, сгенерированный Вашим классом, должен всегда быть тем же для, классы дают состояние.

Я обычно делаю,

GetHashCode()
{
    int HashCode = this.GetType().ToString().GetHashCode();
    HashCode ^= this.Prop1.GetHashCode();
    etc.

    return HashCode;
}

Некоторые скажут, что хэш-код должен только быть вычислен однажды в объектное время жизни, но я не соглашаюсь с тем (и я, вероятно, неправ).

Используя реализацию по умолчанию, обеспеченную объектом, если у Вас нет той же ссылки на один из Ваших классов, они не будут равны друг другу. Переопределением Равняется и GetHashCode, можно сообщить о равенстве на основе внутренних значений, а не ссылки объектов.

1
ответ дан 23 November 2019 в 21:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: