Каковы принципиальные различия между сборкой мусора в C # и Java?

Много хороших ответов здесь, вот мое дополнение вместе с несколькими модульными тестами, которые можно использовать для проверки правильности, мое решение аналогично приведенному выше @ 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]);
    }
}
30
задан User 00000 28 December 2016 в 23:29
поделиться

3 ответа

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

И в C#, и в Java есть GC, которые пытаются оптимизировать быстрое восстановление множества маленьких объектов. Они предназначены для решения одной и той же проблемы, они делают это немного разными способами, но как пользователь, технические различия в вашем подходе к их использованию минимальны, даже не существуют для большинства пользователей.

IDisposable не имеет никакого отношения к GC как таковому. Это стандартный способ именования методов, которые иначе назывались бы close, destroy, dispose и т.д., и часто так называются в Java. Существует предложение для Java 7 добавить нечто очень похожее на ключевое слово using, которое будет вызывать аналогичный метод close.

"Деструкторы" в C# относятся к финализаторам - это было сделано специально, чтобы запутать программистов C++. :) Сама спецификация CLR называет их финализаторами, точно так же, как это делает JVM.

Есть много способов, которыми отличаются Java и C#/CLR (пользовательские типы значений, свойства, дженерики и целое семейство родственных функций, известных как Linq), но GC - это одна из областей, где вы можете разработать значительное количество программного обеспечения, прежде чем вам придется сильно беспокоиться о разнице между ними.

16
ответ дан 28 November 2019 в 00:26
поделиться

Он не согласен с деструкторами. Вам нужно не использовать деструкторы в C #, если это не жизненно необходимо. И если вы их используете, вам следует вызвать SuppressFinalize (), если вы знаете, что объект находится в состоянии, когда код деструктора больше не нужен (чаще всего потому, что такая же очистка произошла при вызове IDisposable.Dispose (). Если у объекта есть деструктор и SuppressFinalize не был вызван, он будет жить дольше (так что у него может быть вызван этот деструктор).

На сборщик мусора, безусловно, можно положиться. На него нельзя полагаться, чтобы вызвать деструктор, или сделать это в течение определенного промежутка времени, но дело не в том, что он ненадежен, а в том, что он надежен при сборе мусора, что является его задачей!

Я мало что знаю об этом. сборщик мусора Java, и я не сомневаюсь, что он прав, говоря, что их нельзя рассматривать как друг друга, когда вы переходите к более тонким деталям, хотя я бы ради Java-программистов надеялся, что это может быть большую часть времени думали о .NET - то есть вообще не думать об этом, обычно вы не авеню.

3
ответ дан 28 November 2019 в 00:26
поделиться

Боюсь, ваш коллега ошибается, но не верьте мне на слово для этого. Давайте устроим фестиваль ссылок!

Вот несколько хороших статей о 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

2
ответ дан 28 November 2019 в 00:26
поделиться