2015-06-25 4 views
4

Недавно я был назначен на некоторые работы по техническому обслуживанию существующего приложения. Я наткнулся на следующий код:C# Generics «in» ключевое слово

public interface IEntityService<T, in TKey> 
{ 
    T GetEntityById(TKey id);  
    IEnumerable<T> GetAll();  
    void Update(T entity);  
    void Delete(TKey key); 
} 

Я не уверен, что in ключевое слово делает для второго родового аргумента TKey.

я наткнулся на следующую MSDN статьи, (должна) объяснить это мне совершенно:
in (Generic Modifier) (C# Reference)

Однако, я не действительно понять. Вот что он говорит:

Для параметров типового типа ключевое слово in указывает, что параметр контравариантен. Вы можете использовать ключевое слово in в общих интерфейсах и делегатах .

Контравариантность позволяет использовать менее производный тип , чем указанный общий параметр. Это позволяет использовать для неявного преобразования классов, реализующих вариантные интерфейсы и неявное преобразование типов делегатов. Ковариация и . Контравариантность в параметрах общего типа поддерживается для ссылочных типов , но они не поддерживаются для типов значений.

Тип может быть объявлено контравариантным в общем интерфейсе или делегировать, если это используется только как тип аргументов методы и не используется в качестве возвращаемого типа метода . Параметры Ref и out не могут быть вариантами.

Интерфейс , который имеет контравариантным параметр типа позволяет его методы, чтобы принять аргументы менее производных типов, чем те, которые указаны в параметре типа интерфейса . Например, поскольку в .NET Framework 4, в интерфейсе IComparer , тип T является контравариантным, вы можете назначить объект типа типа IComparer (Of Person) объекту типа IComparer (Of Employee) без использования каких-либо специальное преобразование методов, если Employee наследует Person.

Контравариантный делегат может быть назначен другому делегату того же типа, но с менее производным параметром типа .

Я предполагаю, что это имеет смысл, но особенно со ссылкой на

контрвариация позволяет использовать менее производный тип, чем тот указанным родовым параметром.

Как это может быть использовано для int? Есть ли какой-либо «менее производный тип», который я когда-либо пропустил?

+0

читать [это] (https://msdn.microsoft.com/en-us/library/dd799517 (v = vs.110) .aspx) – dotctor

+0

'int' - тип значения, и, как вы указали, * ковариация и контравариантность в параметрах общего типа поддерживаются для ссылочных типов * ***, но они не поддерживаются для типов значений ***. –

+0

Спасибо за это. Поэтому ответ заключается в том, что он ничего не делает и, вероятно, не должен быть там, правильно? Хотя он и научил меня разбросу и неизменности! Так что ничего плохого ;-) – bgs264

ответ

3

Отмечу, что единственная ссылка на int находится в последней строке вашего вопроса. Вы уверены, что IEntityService<> должен использоваться только с ключами int?Вероятно, он был построен для Compound Key (первичных ключей, состоящих из нескольких столбцов)

Теперь в NHibernate, например, для составных ключей используются целый класс, чтобы представить их, чтобы вы могли иметь для таблицы MyTable

class MyTableKey 
{ 
    public int Code; 
    public int SubCode; 
} 

Если у вас есть дополнительный стол MuSubtable, подключенного к этой таблице вы могли бы иметь

class MySubtableKey : MyTableKey 
{ 
    public int SubSubCode; 
} 

где MySubtable является таблицей, которая имеет в качестве первичного ключа полной первичной ки y of MyTable (Code + SubCode) плюс еще одно поле (SubSubCode).

Смежные вопросы