Много хороших ответов здесь, вот мое дополнение вместе с несколькими модульными тестами, которые можно использовать для проверки правильности, мое решение аналогично приведенному выше @ Rianne, но использует ISet для обеспечения времени поиска O (1) на заменяемых персонажах (и также похоже на решение Linq @Albin Sunnanbo).
using System;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Returns a string with the specified characters removed.
/// </summary>
/// <param name="source">The string to filter.</param>
/// <param name="removeCharacters">The characters to remove.</param>
/// <returns>A new <see cref="System.String"/> with the specified characters removed.</returns>
public static string Remove(this string source, IEnumerable<char> removeCharacters)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (removeCharacters == null)
{
throw new ArgumentNullException("removeCharacters");
}
// First see if we were given a collection that supports ISet
ISet<char> replaceChars = removeCharacters as ISet<char>;
if (replaceChars == null)
{
replaceChars = new HashSet<char>(removeCharacters);
}
IEnumerable<char> filtered = source.Where(currentChar => !replaceChars.Contains(currentChar));
return new string(filtered.ToArray());
}
Тест NUnit (2.6+) здесь
using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
[TestFixture]
public class StringExtensionMethodsTests
{
[TestCaseSource(typeof(StringExtensionMethodsTests_Remove_Tests))]
public void Remove(string targetString, IEnumerable<char> removeCharacters, string expected)
{
string actual = StringExtensionMethods.Remove(targetString, removeCharacters);
Assert.That(actual, Is.EqualTo(expected));
}
[TestCaseSource(typeof(StringExtensionMethodsTests_Remove_ParameterValidation_Tests))]
public void Remove_ParameterValidation(string targetString, IEnumerable<char> removeCharacters)
{
Assert.Throws<ArgumentNullException>(() => StringExtensionMethods.Remove(targetString, removeCharacters));
}
}
internal class StringExtensionMethodsTests_Remove_Tests : IEnumerable
{
public IEnumerator GetEnumerator()
{
yield return new TestCaseData("My name @is ,Wan.;'; Wan", new char[] { '@', ',', '.', ';', '\'' }, "My name is Wan Wan").SetName("StringUsingCharArray");
yield return new TestCaseData("My name @is ,Wan.;'; Wan", new HashSet<char> { '@', ',', '.', ';', '\'' }, "My name is Wan Wan").SetName("StringUsingISetCollection");
yield return new TestCaseData(string.Empty, new char[1], string.Empty).SetName("EmptyStringNoReplacementCharactersYieldsEmptyString");
yield return new TestCaseData(string.Empty, new char[] { 'A', 'B', 'C' }, string.Empty).SetName("EmptyStringReplacementCharsYieldsEmptyString");
yield return new TestCaseData("No replacement characters", new char[1], "No replacement characters").SetName("StringNoReplacementCharactersYieldsString");
yield return new TestCaseData("No characters will be replaced", new char[] { 'Z' }, "No characters will be replaced").SetName("StringNonExistantReplacementCharactersYieldsString");
yield return new TestCaseData("AaBbCc", new char[] { 'a', 'C' }, "ABbc").SetName("CaseSensitivityReplacements");
yield return new TestCaseData("ABC", new char[] { 'A', 'B', 'C' }, string.Empty).SetName("AllCharactersRemoved");
yield return new TestCaseData("AABBBBBBCC", new char[] { 'A', 'B', 'C' }, string.Empty).SetName("AllCharactersRemovedMultiple");
yield return new TestCaseData("Test That They Didn't Attempt To Use .Except() which returns distinct characters", new char[] { '(', ')' }, "Test That They Didn't Attempt To Use .Except which returns distinct characters").SetName("ValidateTheStringIsNotJustDistinctCharacters");
}
}
internal class StringExtensionMethodsTests_Remove_ParameterValidation_Tests : IEnumerable
{
public IEnumerator GetEnumerator()
{
yield return new TestCaseData(null, null);
yield return new TestCaseData("valid string", null);
yield return new TestCaseData(null, new char[1]);
}
}
Советы, которые вам дали, в целом, полная чушь.
И в C#, и в Java есть GC, которые пытаются оптимизировать быстрое восстановление множества маленьких объектов. Они предназначены для решения одной и той же проблемы, они делают это немного разными способами, но как пользователь, технические различия в вашем подходе к их использованию минимальны, даже не существуют для большинства пользователей.
IDisposable
не имеет никакого отношения к GC как таковому. Это стандартный способ именования методов, которые иначе назывались бы close
, destroy
, dispose
и т.д., и часто так называются в Java. Существует предложение для Java 7 добавить нечто очень похожее на ключевое слово using
, которое будет вызывать аналогичный метод close
.
"Деструкторы" в C# относятся к финализаторам - это было сделано специально, чтобы запутать программистов C++. :) Сама спецификация CLR называет их финализаторами, точно так же, как это делает JVM.
Есть много способов, которыми отличаются Java и C#/CLR (пользовательские типы значений, свойства, дженерики и целое семейство родственных функций, известных как Linq), но GC - это одна из областей, где вы можете разработать значительное количество программного обеспечения, прежде чем вам придется сильно беспокоиться о разнице между ними.
Он не согласен с деструкторами. Вам нужно не использовать деструкторы в C #, если это не жизненно необходимо. И если вы их используете, вам следует вызвать SuppressFinalize (), если вы знаете, что объект находится в состоянии, когда код деструктора больше не нужен (чаще всего потому, что такая же очистка произошла при вызове IDisposable.Dispose (). Если у объекта есть деструктор и SuppressFinalize не был вызван, он будет жить дольше (так что у него может быть вызван этот деструктор).
На сборщик мусора, безусловно, можно положиться. На него нельзя полагаться, чтобы вызвать деструктор, или сделать это в течение определенного промежутка времени, но дело не в том, что он ненадежен, а в том, что он надежен при сборе мусора, что является его задачей!
Я мало что знаю об этом. сборщик мусора Java, и я не сомневаюсь, что он прав, говоря, что их нельзя рассматривать как друг друга, когда вы переходите к более тонким деталям, хотя я бы ради Java-программистов надеялся, что это может быть большую часть времени думали о .NET - то есть вообще не думать об этом, обычно вы не авеню.
Боюсь, ваш коллега ошибается, но не верьте мне на слово для этого. Давайте устроим фестиваль ссылок!
Вот несколько хороших статей о GC: http://msdn.microsoft.com/en-us/magazine/bb985010.aspx http://msdn.microsoft.com/en-us/magazine/bb985011.aspx
Также, Maoni's В WebLog есть несколько замечательных вещей (они также познакомят вас с последними новостями, поскольку статьи выше довольно старые): http://blogs.msdn.com/b/maoni/
Кроме того, буквально на этой неделе Раймонд Чен делает серию статей о GC: http://blogs.msdn.com/b/oldnewthing/archive/2010/08/13/10049634.aspx
Вот хорошее обсуждение использования Dispose и Finalization: http://www.bluebytesoftware.com/blog/2005/04/08/DGUpdateDisposeFinalizationAndResourceManagement.aspx