#c#
#c# #обобщения #синтаксис #псевдоним #использование
Вопрос:
Поскольку я использую два разных общих пространства имен коллекций ( System.Collections.Generic
и Iesi.Collections.Generic
), у меня возникают конфликты. В других частях проекта я использую как фреймворки nunit, так и mstest, но уточняю, что при вызове Assert
я хочу использовать версию nunit с помощью
using Assert = NUnit.Framework.Assert;
Который отлично работает, но я хочу сделать то же самое с универсальными типами. Однако следующие строки не работают
using ISet = System.Collections.Generic.ISet;
using ISet<> = System.Collections.Generic.ISet<>;
Кто-нибудь знает, как сообщить .net, как использовать инструкцию using с обобщениями?
Комментарии:
1. Это иногда запрашиваемая функция. Это было в списке возможных функций в течение длительного времени, но никогда не было достаточно высоким приоритетом для реальной реализации.
2. Эрик, я впервые сталкиваюсь с этой проблемой, поскольку платформа .net 4.0 добавила ISet<> и Iesi. Библиотеки dll Collections нацелены на 3.5. Обычно другие разработчики хорошо относятся к тому, чтобы не конфликтовать со стандартным именованием .net.
3. Почему у вас это в двух разных пространствах имен? Можете ли вы предоставить дополнительную информацию?
4. Я бы сформулировал это по-другому. Намеренное использование одного и того же имени для двух разных вещей будет неудобным. Это работает лучше всего, если у вас крайне маловероятно
using
одновременное использование двух пространств имен.5. @EricLippert При преобразовании кода из Java или Haskell или других языков, поддерживающих точный импорт символов (т. Е.
import myModule.MyClass;
В Java, я обнаружил, что это серьезный недостаток C #, потому что вам нужноusing
все,System.Collections.Generic
даже если вам нужно толькоIEnumerable<>
для вашего выражения LINQ. Java не разрешает переименование, но я думаю, что переименование импорта на самом деле запрашивается «иногда», а не точный импорт / использование.
Ответ №1:
К сожалению, using
директива не делает то, что вы хотите. Вы можете сказать:
using Frob = System.String;
и
using ListOfInts = System.Collections.Generic.List<System.Int32>;
но вы не можете сказать
using Blob<T> = System.Collections.Generic.List<T>
или
using Blob = System.Collections.Generic.List
Это недостаток языка, который никогда не исправлялся.
Комментарии:
1. Каков наилучший способ лоббировать эту функцию?
2. @miniBill: попробуйте опубликовать на форуме по языковому дизайну по адресу Roslyn.codeplex.com .
3. Здесь есть предложение. Я тоже хотел бы иметь эту функцию.
Ответ №2:
Я думаю, вам лучше использовать псевдонимы самих пространств имен, а не универсальных типов (что, я думаю, невозможно).
Так, например:
using S = System.Collections.Generic;
using I = Iesi.Collections.Generic;
Затем для BCL ISet<int>
, например:
S.ISet<int> integers = new S.HashSet<int>();
Комментарии:
1. Очень хорошее предложение! Только что столкнулся с точно такой же проблемой, и это не сразу пришло мне в голову.
2. Это работает только в том случае, если это пространство имен, которое является длинным битом. Если сами параметры типа имеют длинные имена типов, вам не повезло.
3. Просто столкнулся с той же проблемой. Я хочу использовать константы, определенные в универсальном классе, в качестве значений параметров по умолчанию для конструктора, и их всего 4, поэтому мне нужно ввести полное, длинное имя класса с его общими параметрами плюс имя константы. Это можно было бы решить, если бы язык разрешал использовать операторы внутри универсального класса, например
using C = Long.Name<TKey,TValue>
. За пределами класса общие параметры неизвестны, поэтому это бесполезно.
Ответ №3:
Единственный способ, которым вы можете создать псевдоним универсального типа, — это специализировать его следующим образом.
using IntSet = System.Collections.Generic.ISet<int>;
Вы не можете использовать псевдоним открытого универсального типа, как вы сделали в своем примере:
using MySet = System.Collections.Generic.ISet<>;
Комментарии:
1. Спасибо, Стив, я смогу использовать это позже!
2. Почему ваш первый пример не будет компилироваться на VS2017?
Ответ №4:
Ваше имя псевдонима совпадает с именем самого класса, поэтому у вас все еще есть двусмысленность, как если бы у вас было using
для каждого пространства имен. Дайте псевдониму класса другое имя, т.е.:
using FirstNamespace;
using OtherObject = SecondNamespace.MyObject;
public class Foo
{
public void Bar()
{
MyObject first = new MyObject;//will be the MyObject from the first namespace
OtherObject second = new OtherObject;
}
}
Ответ №5:
В некоторых случаях вы можете использовать наследование:
public class MyList<T1, T2> : List<Tuple<IEnumerable<HashSet<T1>>, IComparable<T2>>> { }
public void Meth()
{
var x = new MyList<int, bool>();
}
Ответ №6:
Вы можете создать псевдоним класса, выполнив :
using Test = NameSpace.MyClass;
Только если класс НЕ является универсальным.
Комментарии:
1. Вы можете создать псевдоним универсального класса, вам просто нужно указать конкретный тип в псевдониме, а не оставлять его универсальным.