тестовое задание
От: mig84 Россия  
Дата: 05.12.13 15:32
Оценка:
Здравствуйте. Не так давно выполнил (во всяком случае так считал) тестовое задание. Описание задачи:
Спроектируйте и реализуйте класс-коллекцию для хранения элементов, имеющих уникальный составной ключ [Id, Name] (Id и Name – компоненты ключа, могу быть произвольного типа). Вы можете использовать любую встроенную коллекцию .NET Framework.
Предоставьте необходимые с вашей точки зрения методы для этой коллекции, а так же методы для эффективного по скорости получения элементов по их Id ИЛИ Name.
Программа должна содержать пример использования коллекции с идентификатором ключа в виде пользовательского типа (т.е. Id в ключе – UserType, объекты UserType должны сравниваться по значению).
Дополнительно: Создайте потокобезопасную реализацию этой коллекции (не использовать коллекции из пространства имён System.Collections.Concurrent).

То, что я предложил в качестве решения:


Элемент и UserType:

    /// <summary>
    /// Элемент коллекции
    /// </summary>
    public class MyElement
    {
        private UserType id;
        private String name;

        public String Name
        {
            get { return name; }
            set { name = value; }
        }

        public UserType Id
        {
            get { return id; }
            set { id = value; }
        }

        public override int GetHashCode()
        {
            return Name.GetHashCode() ^ Id.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (!(obj is MyElement))
            {
                MyElement el = (MyElement)obj;
                return Id == el.Id && Name == el.Name;
            }
            else
            {
                return false;
            }
        }

        public override string ToString()
        {
            return String.Format("Id:{0}, Name:{1}",id.Content.ToString(), Name);
        }

    }
    /// <summary>
    /// Тип для поля Id
    /// </summary>
    public struct UserType
    {
        private int content;
        public int Content
        {
            get { return content; }
            set { content = value; }
        }

        public override int GetHashCode()
        {
            return Content^Content;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is UserType))
            {
                UserType ut = (UserType)obj;
                return Content == ut.Content;
            }
            else
            {
                return false;
            }
        }

        public static Boolean operator == (UserType ut1, UserType ut2)
        {
            return ut1.Content == ut2.Content;
        }

        public static Boolean operator != (UserType ut1, UserType ut2)
        {
            return ut1.Content != ut2.Content;
        
        }

        public override string ToString()
        {
            return Content.ToString();
        }

    }


Индекс:

    /// <summary>
    /// Индекс для коллекции
    /// </summary>
    public struct MyId : IEquatable<MyId>
    {
        private readonly UserType id;
        private readonly String name;

        public UserType Id
        {
            get
            {
                return id;
            }
        }

        public String Name
        {
            get
            {
                return name;
            }
        }

        //public MyId(UserType _id, String _name)
        //{
        //    id = _id;
        //    name = _name;
        //}

        public MyId(MyElement element)
        {
            id = element.Id;
            name = element.Name;
        }

        public override int GetHashCode()
        {
            return id.GetHashCode() ^ name.GetHashCode();
        }

        public bool Equals(MyId other)
        {
            if ((object)other == null)
            {
                return false;
            }
            else
            {
                return id == other.id && name == other.name;

            }
        }

        public override bool Equals(object obj)
        {
            return Equals((MyId)obj);
        }

        public static Boolean operator == (MyId u1, MyId u2)
        {
            return (u1.id == u2.id) && (u1.name == u2.name);
        }

        public static Boolean operator != (MyId u1, MyId u2)
        {
            return (u1.id == u2.id) || (u1.name == u2.name);
        }

        public override string ToString()
        {
            return String.Format("Key(id={0}, name={1})", id.ToString(), name);
        }
    }


Собственно, коллекция:
    /// <summary>
    /// Класс-коллекция. Потокобезопасность реализована для метода Add.
    /// Т.к. коллекция наследует от Dictionary, она поддерживает необходимые базовые методы
    /// </summary>
    /// <typeparam name="TKey">В качестве ключа используется MyId</typeparam>
    /// <typeparam name="TValue">Элемент коллекции</typeparam>
    public class MyCollection<TKey, TValue> : Dictionary<MyId, TValue>
    {
        private readonly object syncRoot = new object();
        private Dictionary<MyId, TValue> _myCollection = new Dictionary<MyId, TValue>();


        /// <summary>
        /// Перекрываем метод вставки в коллекцию для реализации потокобезопасности.
        /// Примечание: при попытка вставить элемент с повторяющимся индексом просто игнорируем вставку.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public new void Add(MyId key, TValue value)
        {
            lock (syncRoot)
            {
                if (!this.ContainsKey(key))
                {
                    base.Add(key, value);
                }
                
            }

        }

        #region Реализация методов поиска указанных в задании

        public MyElement GetElementById(UserType _id)
        {
            dynamic result;
            lock (syncRoot)
            {
                result = this.Where(x => x.Key.Id == _id).SingleOrDefault().Value;
            }
            if (result is MyElement)
            {
                return result as MyElement;
            }
            else
            {
                return null;
            }
        }

        public MyElement GetElementByName(String _name)
        {
            dynamic result;
            lock (syncRoot)
            {
                result = this.Where(x => x.Key.Name == _name).SingleOrDefault().Value;
            }

            if (result is MyElement)
            {
                return result as MyElement;
            }
            else
            {
                return null;
            }

        }

        public MyElement GetElementByIdOrName(object o)
        {
            if (o is String)
            {
                return GetElementByName((string)o);
            }
            else if (o is UserType)
            {
                return GetElementById((UserType)o);
            }
            else
            {
                return null;
            }
            
        }

        #endregion

    }


Этот вариант решения, как видно, не понравился проверявшему.
Буду признателен, если "ткнете носом" в ошибки. Понимаю, что, возможно подошел к решению довольно формально, но по требованиям вроде все реализовал. Или чего-то не так понял.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.