Это должно работать: (редактирование на месте)
import fileinput
# Does a list of files, and
# redirects STDOUT to the file in question
for line in fileinput.input(files, inplace = 1):
print line.replace("foo", "bar"),
Чтобы создать экземпляр универсального типа в функции, вы должны ограничить его с помощью флага «новый».
public static string GetAllItems<T>(...) where T : new()
Однако это будет работать только тогда, когда вы захотите вызвать конструктор, у которого нет параметров. Здесь не тот случай. Вместо этого вам нужно будет предоставить другой параметр, который позволяет создавать объект на основе параметров. Самый простой - это функция.
public static string GetAllItems<T>(..., Func<ListItem,T> del) {
...
List<T> tabListItems = new List<T>();
foreach (ListItem listItem in listCollection)
{
tabListItems.Add(del(listItem));
}
...
}
Затем вы можете назвать это так
GetAllItems<Foo>(..., l => new Foo(l));
Если все - Вы, потребность является convertion от ListItem до Вашего типа T, можно реализовать этот convertion в классе T как оператор преобразования.
public class T
{
public static implicit operator T(ListItem listItem) => /* ... */;
}
public static string GetAllItems(...)
{
...
List<T> tabListItems = new List<T>();
foreach (ListItem listItem in listCollection)
{
tabListItems.Add(listItem);
}
...
}
Это не сработает в вашей ситуации. Вы можете указать только ограничение, что у него есть пустой конструктор:
public static string GetAllItems<T>(...) where T: new()
Что вы могли бы сделать, так это использовать внедрение свойств, определив этот интерфейс:
public interface ITakesAListItem
{
ListItem Item { set; }
}
Затем вы можете изменить свой метод следующим образом:
public static string GetAllItems<T>(...) where T : ITakesAListItem, new()
{
...
List<T> tabListItems = new List<T>();
foreach (ListItem listItem in listCollection)
{
tabListItems.Add(new T() { Item = listItem });
}
...
}
Другой альтернативой является Метод Func
, описанный JaredPar.
Вам нужно добавить where T: new (), чтобы компилятор знал, что T гарантированно предоставит конструктор по умолчанию.
public static string GetAllItems<T>(...) where T: new()
Я считаю, что вам нужно ограничить T с помощью оператора where разрешить только объекты с новым конструктором.
ПРАВИЛЬНО теперь он принимает все, включая объекты без него.
Если вы просто хотите инициализировать поле или свойство члена параметром конструктора, в C #> = 3 вы можете сделать это очень просто:
public static string GetAllItems<T>(...) where T : InterfaceOrBaseClass, new()
{
...
List<T> tabListItems = new List<T>();
foreach (ListItem listItem in listCollection)
{
tabListItems.Add(new T{ BaseMemberItem = listItem }); // No error, BaseMemberItem owns to InterfaceOrBaseClass.
}
...
}
Это это то же самое, что сказал Гарри Шатлер, но я хотел бы добавить дополнительное примечание.
Конечно, вы можете использовать уловку свойств, чтобы делать больше, чем просто устанавливать значение поля. Свойство "set ()" может инициировать любую обработку, необходимую для настройки связанных с ним полей, и любую другую потребность в сам объект, включая проверку того, должна ли происходить полная инициализация перед использованием объекта, имитируя полную конструкцию (да, это уродливый обходной путь, но он преодолевает ограничение M $ new ()).
Я не могу с уверенностью сказать, запланированная ли это дыра или случайный побочный эффект, но это работает.
Очень забавно, как MS-люди добавляют новые функции к языку и, кажется, не проводят полного анализа побочных эффектов. Все общие вещи являются хорошим доказательством этого ...
{{ 1}}Поскольку никто не удосужился опубликовать ответ «Отражение» (который я лично считаю лучшим ответом), вот что:
public static string GetAllItems<T>(...) where T : new()
{
...
List<T> tabListItems = new List<T>();
foreach (ListItem listItem in listCollection)
{
Type classType = typeof(T);
ConstructorInfo classConstructor = classType.GetConstructor(new Type[] { listItem.GetType() });
T classInstance = (T)classConstructor.Invoke(new object[] { listItem });
tabListItems.Add(classInstance);
}
...
}
Изменить: этот ответ устарел из-за .NET 3.5. Activator.CreateInstance, однако он по-прежнему полезен в более старых версиях .NET.