You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,246 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DataRowComparer.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="true">[....]</owner>
|
||||
// <owner current="true" primary="false">spather</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Data.DataSetExtensions;
|
||||
|
||||
namespace System.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// This class implements IEqualityComparer using value based semantics
|
||||
/// when comparing DataRows.
|
||||
/// </summary>
|
||||
public static class DataRowComparer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the singleton instance of the data row comparer.
|
||||
/// </summary>
|
||||
public static DataRowComparer<DataRow> Default { get { return DataRowComparer<DataRow>.Default; } }
|
||||
|
||||
internal static bool AreEqual(object a, object b)
|
||||
{
|
||||
if (Object.ReferenceEquals(a, b))
|
||||
{ // same reference or (null, null) or (DBNull.Value, DBNull.Value)
|
||||
return true;
|
||||
}
|
||||
if (Object.ReferenceEquals(a, null) || Object.ReferenceEquals(a, DBNull.Value) ||
|
||||
Object.ReferenceEquals(b, null) || Object.ReferenceEquals(b, DBNull.Value))
|
||||
{ // (null, non-null) or (null, DBNull.Value) or vice versa
|
||||
return false;
|
||||
}
|
||||
return (a.Equals(b) || (a.GetType().IsArray && CompareArray((Array)a, b as Array)));
|
||||
}
|
||||
|
||||
private static bool AreElementEqual(object a, object b)
|
||||
{
|
||||
if (Object.ReferenceEquals(a, b))
|
||||
{ // same reference or (null, null) or (DBNull.Value, DBNull.Value)
|
||||
return true;
|
||||
}
|
||||
if (Object.ReferenceEquals(a, null) || Object.ReferenceEquals(a, DBNull.Value) ||
|
||||
Object.ReferenceEquals(b, null) || Object.ReferenceEquals(b, DBNull.Value))
|
||||
{ // (null, non-null) or (null, DBNull.Value) or vice versa
|
||||
return false;
|
||||
}
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
private static bool CompareArray(Array a, Array b)
|
||||
{
|
||||
if ((null == b) ||
|
||||
(1 != a.Rank) ||
|
||||
(1 != b.Rank) ||
|
||||
(a.Length != b.Length))
|
||||
{ // automatically consider array's with Rank>1 not-equal
|
||||
return false;
|
||||
}
|
||||
|
||||
int index1 = a.GetLowerBound(0);
|
||||
int index2 = b.GetLowerBound(0);
|
||||
if (a.GetType() == b.GetType() && (0 == index1) && (0 == index2))
|
||||
{
|
||||
switch (Type.GetTypeCode(a.GetType().GetElementType()))
|
||||
{
|
||||
case TypeCode.Byte:
|
||||
return DataRowComparer.CompareEquatableArray<Byte>((Byte[])a, (Byte[])b);
|
||||
case TypeCode.Int16:
|
||||
return DataRowComparer.CompareEquatableArray<Int16>((Int16[])a, (Int16[])b);
|
||||
case TypeCode.Int32:
|
||||
return DataRowComparer.CompareEquatableArray<Int32>((Int32[])a, (Int32[])b);
|
||||
case TypeCode.Int64:
|
||||
return DataRowComparer.CompareEquatableArray<Int64>((Int64[])a, (Int64[])b);
|
||||
case TypeCode.String:
|
||||
return DataRowComparer.CompareEquatableArray<String>((String[])a, (String[])b);
|
||||
}
|
||||
}
|
||||
|
||||
//Compare every element. But don't recurse if we have Array of array.
|
||||
int length = index1 + a.Length;
|
||||
for (; index1 < length; ++index1, ++index2)
|
||||
{
|
||||
if (!AreElementEqual(a.GetValue(index1), b.GetValue(index2)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool CompareEquatableArray<TElem>(TElem[] a, TElem[] b) where TElem : IEquatable<TElem>
|
||||
{
|
||||
if (Object.ReferenceEquals(a, b))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Object.ReferenceEquals(a, null) ||
|
||||
Object.ReferenceEquals(b, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (a.Length != b.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < a.Length; ++i)
|
||||
{
|
||||
if (!a[i].Equals(b[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class implements IEqualityComparer using value based semantics
|
||||
/// when comparing DataRows.
|
||||
/// </summary>
|
||||
public sealed class DataRowComparer<TRow> : IEqualityComparer<TRow> where TRow : DataRow
|
||||
{
|
||||
/// <summary>
|
||||
/// Private constructor to prevent initialization outside of Default singleton instance.
|
||||
/// </summary>
|
||||
private DataRowComparer() { }
|
||||
|
||||
private static DataRowComparer<TRow> _instance = new DataRowComparer<TRow>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the singleton instance of the data row comparer.
|
||||
/// </summary>
|
||||
public static DataRowComparer<TRow> Default { get { return _instance; } }
|
||||
|
||||
/// <summary>
|
||||
/// This method compares to DataRows by doing a column by column value based
|
||||
/// comparision.
|
||||
/// </summary>
|
||||
/// <param name="leftRow">
|
||||
/// The first input DataRow
|
||||
/// </param>
|
||||
/// <param name="rightRow">
|
||||
/// The second input DataRow
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// True if rows are equal, false if not.
|
||||
/// </returns>
|
||||
public bool Equals(TRow leftRow, TRow rightRow)
|
||||
{
|
||||
if (Object.ReferenceEquals(leftRow, rightRow))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Object.ReferenceEquals(leftRow, null) ||
|
||||
Object.ReferenceEquals(rightRow, null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (leftRow.RowState == DataRowState.Deleted || rightRow.RowState == DataRowState.Deleted)
|
||||
{
|
||||
throw DataSetUtil.InvalidOperation(Strings.DataSetLinq_CannotCompareDeletedRow);
|
||||
}
|
||||
|
||||
int count = leftRow.Table.Columns.Count;
|
||||
if (count != rightRow.Table.Columns.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
if (!DataRowComparer.AreEqual(leftRow[i], rightRow[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This mtheod retrieves a hash code for the source row.
|
||||
/// </summary>
|
||||
/// <param name="row">
|
||||
/// The source DataRow
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// HashCode for row based on values in the row.
|
||||
/// </returns>
|
||||
public int GetHashCode(TRow row)
|
||||
{
|
||||
DataSetUtil.CheckArgumentNull(row, "row");
|
||||
|
||||
if (row.RowState == DataRowState.Deleted)
|
||||
{
|
||||
throw DataSetUtil.InvalidOperation(Strings.DataSetLinq_CannotCompareDeletedRow);
|
||||
}
|
||||
|
||||
int hash = 0;
|
||||
Debug.Assert(row.Table != null);
|
||||
if (row.Table.Columns.Count > 0)
|
||||
{
|
||||
// if the row has at least one column, then use the first column value
|
||||
object value = row[0];
|
||||
|
||||
Type valueType = value.GetType();
|
||||
if (valueType.IsArray)
|
||||
{
|
||||
Array array = value as Array;
|
||||
|
||||
if (array.Rank > 1)
|
||||
{
|
||||
hash = value.GetHashCode();
|
||||
}
|
||||
else if (array.Length > 0)
|
||||
{
|
||||
hash = array.GetValue(array.GetLowerBound(0)).GetHashCode();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.ValueType vt = value as System.ValueType;
|
||||
|
||||
// have to unbox value types.
|
||||
if (vt != null)
|
||||
{
|
||||
hash = vt.GetHashCode();
|
||||
}
|
||||
else
|
||||
{
|
||||
hash = value.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
// if table has no columns, the hash code is 0
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user