C# 使用IComparable比较数组
我对学校的任务有问题 假设类列表是生成随机数组的构造函数 类List1继承自类列表,并使用IComparable比较第一个元素,然后比较第二个元素等。空白是0{1,1,1} 我注意到从列表继承到列表1的构造函数不是继承的,所以我不知道在哪里以及如何使用IComparableC# 使用IComparable比较数组,c#,arrays,inheritance,C#,Arrays,Inheritance,我对学校的任务有问题 假设类列表是生成随机数组的构造函数 类List1继承自类列表,并使用IComparable比较第一个元素,然后比较第二个元素等。空白是0{1,1,1} 我注意到从列表继承到列表1的构造函数不是继承的,所以我不知道在哪里以及如何使用IComparable class List1 : List,IComparable<List1> { public int CompareTo(List1 x){ return this.CompareTo(x
class List1 : List,IComparable<List1>
{
public int CompareTo(List1 x){
return this.CompareTo(x);
}
}
我不能把这句话理解为一个问题,因为缺少继承的构造函数对我来说似乎完全独立于如何使用IComparable
那么,让我们分别解决这两个问题:
没有继承构造函数是正确的。也就是说,尽管它们仍然存在,但它们只能由派生类型调用,不能由外部代码直接使用。如果基类没有无参数构造函数,那么作为派生类的实现者,您有责任提供一个构造函数,然后调用相应的基类构造函数。每个类都会有一些构造函数。例如:
类列表1:列表
{
public List1int count:basecount{}
}
这里我假设列表是除.NET列表类型之外的其他类型,即它不是泛型的,是在您自己的上下文中定义的
通过这种方式,您可以提供必要的构造函数,并通过使用:basecount将参数值传递给构造函数来确保调用了正确的基构造函数
如何使用IComparable。在我看来,这是你任务的关键。我为你写代码是在伤害你。不过,我会尽量详细说明这些说明,以帮助您理解他们似乎在问什么。当然,您的老师是您接受这些建议的最佳人选。
你有两个不同的作业。两者都要求您实现接口IComparable,因此您需要做的第一件事是确保您理解实现接口意味着什么。你…吗?接口是一种契约。在任何接口声明中,都描述了该接口的实现需要提供的成员。如果您看一下,就会发现它只需要实现一个成员:CompareTo方法。
因此,您的任务归结为如何为两个必需的子类List1和List2中的每一个实现该方法。这两种实现的基本思想是相同的,但具体细节不同。
在第一种情况下,比较将根据集合的内容对List1的两个实例进行排序,其中这些实例的顺序由每个实例中数组相同位置的第一个非相等元素的顺序确定。在给出的示例中,{1,1,1}被视为小于{1,2},因为当您比较List1的每个实例的每个位置的元素时,元素不同的第一个对应位置是第二个位置索引1,其中{1,1,1}的值为1,{1,2}的值为2。值1小于值2,因此{1,1,1}的整个实例小于{1,2}的整个实例。不幸的是,您在文章中描述的赋值不清楚如何对实例排序,其中一个的基础列表比另一个的基础列表短,但在这些元素位置上具有完全相同的值。我会将较短的列表视为少于,但这显然不是唯一有效的方法。
在任务的第二部分中,实现List2,唯一需要比较的是列表的长度。这应该比赋值的第一部分更容易实现,因为每个List2实例中只有一个值可比较,即tabb.Length。
请注意,在这两种情况下,您都可以利用int还实现了IComparable这一事实,因此可以使用其CompareTo方法来确定类的每个实例中的对应值是否彼此小于、等于或大于。
我希望这足以让你找到正确的方向。如果你需要更多的帮助,你可能应该咨询你的导师。他们会确切地知道他们想为你提供多少帮助,而实际上却没有为你完成任务。对不起,我不是故意要全力以赴的。但事情就这样发生了。很晚了。它使我感兴趣,尤其是需要能够测试它,即使随机数的要求使它很难测试 我来做的解决方案是将列表与其填充方式分开。这样,出于测试目的,我可以替换一个填充器,该填充器正好插入我想要的值。这样我就可以创建测试场景
// This is the base list - it just requires something to populate it.
public class IntegerList : List<int>
{
public IntegerList(IIntegerListPopulator populator, int size)
{
populator.PopulateList(this, size);
}
}
// Interface and implementation to populate a list with random numbers.
public interface IIntegerListPopulator
{
void PopulateList(List<int> target, int size);
}
public class RandomIntegerListPopulator : IIntegerListPopulator
{
public void PopulateList(List<int> target, int size)
{
var random = new Random();
for (var i = 0; i < size; i++)
{
target.Add(random.Next(0, 100));
}
}
}
// Compares by values, but the populator is injected - needed so that
// the class can be tested.
public class IntegerListThatComparesByValues : IntegerList, IComparable<IntegerListThatComparesByValues>
{
public IntegerListThatComparesByValues(IIntegerListPopulator populator, int size)
: base(populator, size)
{ }
public int CompareTo(IntegerListThatComparesByValues other)
{
return new IntegerListValueComparer().Compare(this, other);
}
}
// Class to perform comparisons by value. There's no real point
// in implementing IComparer since I'm not using it that way,
// but it doesn't hurt.
public class IntegerListValueComparer : IComparer<IntegerList>
{
public int Compare(IntegerList x, IntegerList y)
{
// I made this part up. I don't actually know how
// you want to handle nulls.
if (x == null && y == null) return 0;
if (x == null) return 1;
if (y == null) return -1;
// Always compare the longer one to the shorter.
// if this one is shorter, do the reverse comparison
// and reverse the result.
if (y.Count < x.Count) return -Compare(y, x);
if (x.SequenceEqual(y)) return 0;
for (var index = 0; index < x.Count; index++)
{
var comparison = x[index].CompareTo(y[index]);
if (comparison != 0) return comparison;
}
// If the other list is longer than this one, then assume
// that the next element of this list is 0.
return -y[x.Count];
}
}
public class IntegerListThatComparesByLength : IntegerList, IComparable<IntegerListThatComparesByLength>
{
public IntegerListThatComparesByLength(IIntegerListPopulator populator, int size)
: base(populator, size)
{
}
public int CompareTo(IntegerListThatComparesByLength other)
{
var comparisonByCount = Count.CompareTo(other?.Count ?? 0);
return comparisonByCount != 0
? comparisonByCount
: new IntegerListValueComparer().Compare(this, other);
}
}
// *************************************************************
// These are the concrete classes specified in the requirements.
// *************************************************************
public class RandomIntegerListThatComparesByValues :
IntegerListThatComparesByValues
{
public RandomIntegerListThatComparesByValues(int size)
: base(new RandomIntegerListPopulator(), size)
{ }
}
public class RandomIntegerListThatComparesByLength :
IntegerListThatComparesByLength
{
public RandomIntegerListThatComparesByLength(int size)
: base(new RandomIntegerListPopulator(), size)
{ }
}
// *************************************************************
// The rest is all testing.
// *************************************************************
// Allows me to create class instances that contain the numbers
// I specify instead of random numbers so that I can create
// test cases.
public class IntegerListPopulatorTestDouble : IIntegerListPopulator
{
private readonly int[] _values;
public IntegerListPopulatorTestDouble(params int[] values)
{
_values = values;
}
public void PopulateList(List<int> target, int size)
{
target.AddRange(_values.Take(size));
}
}
[TestClass]
public class IntegerListThatComparesByValuesTests
{
[TestMethod]
public void EmptyListsAreEqual()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(), 0 );
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(), 0);
Assert.AreEqual(0, list1.CompareTo(list2));
}
[TestMethod]
public void ListsWithSameValuesAreEqual()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1,2,3), 3);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1,2,3), 3);
Assert.AreEqual(0, list1.CompareTo(list2));
}
[TestMethod]
public void ListsOfSameLengthComparedByFirstNonEqualValue()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 4), 3);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
}
[TestMethod]
public void MissingElementsOfListAreSortedAsZeros()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3, 4), 4);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
var comparison = list1.CompareTo(list2);
Assert.IsTrue(comparison > 0);
comparison = list2.CompareTo(list1);
Assert.IsTrue(comparison < 0);
}
[TestMethod]
public void MissingElementsOfListAreSortedAsZeros_Case2()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3, -4), 4);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) < 0);
Assert.IsTrue(list2.CompareTo(list1) > 0);
}
}
[TestClass]
public class IntegerListThatComparesByLengthTests
{
[TestMethod]
public void ListsAreComparedByLength()
{
var list1 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3, 4), 4);
var list2 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
Assert.IsTrue(list2.CompareTo(list1) < 0);
}
[TestMethod]
public void ListsOfEqualLengthAreComparedByValue()
{
var list1 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 4), 3);
var list2 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
Assert.IsTrue(list2.CompareTo(list1) < 0);
}
}
我不知道他们是否在学校教授单元测试,但这说明了为什么他们应该这样做。虽然逻辑并不是难以置信的困难,但第一次尝试可能不会成功
T如果不创建一些测试用例来运行它,您怎么知道自己是否正确呢?你的导师怎么知道?如果您修复了一个bug,但却破坏了另一个测试用例,该怎么办?如果你必须调试,每次调试你都会得到不同的随机数。吓人
正是这种随机性让我很反感。如果这些数字总是随机的,那么讲师希望如何观察结果并知道它们是正确的?这是可能的,但目测并不是知道它是否有效的最可靠的方法
在现实生活中,如果没有这些单元测试来告诉我它按预期工作,我就不想把哪怕是稍微复杂的逻辑放到生产系统中
此外,当您阅读需求描述时,可能会感到困惑和不清楚。但是假设我理解了需求,现在您可以查看单元测试并更清楚地了解这段代码应该做什么。否则,其他人可能需要做出改变,如果他们不知道它应该做什么,他们也不知道自己是否破坏了它。如果结果证明我的需求是错误的,那么我可以更改测试以满足正确的需求。测试将失败,然后我修改代码,直到测试通过。请参见此处:这将对您有所帮助。我已经阅读了本主题。仍在与继承权作斗争though@OskarJaglak这不是C++,请根据你实际使用的语言来修改标签。什么是斗争?真正给循环的是,需求指定随机数。不是说你-这是他们给你的任务。有许多场景需要测试。在现实生活中,我想编写单元测试来解释它们,这样我就知道它是有效的。同时考虑测试和处理随机数并非不可能,但如果您希望能够编写单元测试,这将是一个复杂的问题。
// This is the base list - it just requires something to populate it.
public class IntegerList : List<int>
{
public IntegerList(IIntegerListPopulator populator, int size)
{
populator.PopulateList(this, size);
}
}
// Interface and implementation to populate a list with random numbers.
public interface IIntegerListPopulator
{
void PopulateList(List<int> target, int size);
}
public class RandomIntegerListPopulator : IIntegerListPopulator
{
public void PopulateList(List<int> target, int size)
{
var random = new Random();
for (var i = 0; i < size; i++)
{
target.Add(random.Next(0, 100));
}
}
}
// Compares by values, but the populator is injected - needed so that
// the class can be tested.
public class IntegerListThatComparesByValues : IntegerList, IComparable<IntegerListThatComparesByValues>
{
public IntegerListThatComparesByValues(IIntegerListPopulator populator, int size)
: base(populator, size)
{ }
public int CompareTo(IntegerListThatComparesByValues other)
{
return new IntegerListValueComparer().Compare(this, other);
}
}
// Class to perform comparisons by value. There's no real point
// in implementing IComparer since I'm not using it that way,
// but it doesn't hurt.
public class IntegerListValueComparer : IComparer<IntegerList>
{
public int Compare(IntegerList x, IntegerList y)
{
// I made this part up. I don't actually know how
// you want to handle nulls.
if (x == null && y == null) return 0;
if (x == null) return 1;
if (y == null) return -1;
// Always compare the longer one to the shorter.
// if this one is shorter, do the reverse comparison
// and reverse the result.
if (y.Count < x.Count) return -Compare(y, x);
if (x.SequenceEqual(y)) return 0;
for (var index = 0; index < x.Count; index++)
{
var comparison = x[index].CompareTo(y[index]);
if (comparison != 0) return comparison;
}
// If the other list is longer than this one, then assume
// that the next element of this list is 0.
return -y[x.Count];
}
}
public class IntegerListThatComparesByLength : IntegerList, IComparable<IntegerListThatComparesByLength>
{
public IntegerListThatComparesByLength(IIntegerListPopulator populator, int size)
: base(populator, size)
{
}
public int CompareTo(IntegerListThatComparesByLength other)
{
var comparisonByCount = Count.CompareTo(other?.Count ?? 0);
return comparisonByCount != 0
? comparisonByCount
: new IntegerListValueComparer().Compare(this, other);
}
}
// *************************************************************
// These are the concrete classes specified in the requirements.
// *************************************************************
public class RandomIntegerListThatComparesByValues :
IntegerListThatComparesByValues
{
public RandomIntegerListThatComparesByValues(int size)
: base(new RandomIntegerListPopulator(), size)
{ }
}
public class RandomIntegerListThatComparesByLength :
IntegerListThatComparesByLength
{
public RandomIntegerListThatComparesByLength(int size)
: base(new RandomIntegerListPopulator(), size)
{ }
}
// *************************************************************
// The rest is all testing.
// *************************************************************
// Allows me to create class instances that contain the numbers
// I specify instead of random numbers so that I can create
// test cases.
public class IntegerListPopulatorTestDouble : IIntegerListPopulator
{
private readonly int[] _values;
public IntegerListPopulatorTestDouble(params int[] values)
{
_values = values;
}
public void PopulateList(List<int> target, int size)
{
target.AddRange(_values.Take(size));
}
}
[TestClass]
public class IntegerListThatComparesByValuesTests
{
[TestMethod]
public void EmptyListsAreEqual()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(), 0 );
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(), 0);
Assert.AreEqual(0, list1.CompareTo(list2));
}
[TestMethod]
public void ListsWithSameValuesAreEqual()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1,2,3), 3);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1,2,3), 3);
Assert.AreEqual(0, list1.CompareTo(list2));
}
[TestMethod]
public void ListsOfSameLengthComparedByFirstNonEqualValue()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 4), 3);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
}
[TestMethod]
public void MissingElementsOfListAreSortedAsZeros()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3, 4), 4);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
var comparison = list1.CompareTo(list2);
Assert.IsTrue(comparison > 0);
comparison = list2.CompareTo(list1);
Assert.IsTrue(comparison < 0);
}
[TestMethod]
public void MissingElementsOfListAreSortedAsZeros_Case2()
{
var list1 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3, -4), 4);
var list2 = new IntegerListThatComparesByValues(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) < 0);
Assert.IsTrue(list2.CompareTo(list1) > 0);
}
}
[TestClass]
public class IntegerListThatComparesByLengthTests
{
[TestMethod]
public void ListsAreComparedByLength()
{
var list1 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3, 4), 4);
var list2 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
Assert.IsTrue(list2.CompareTo(list1) < 0);
}
[TestMethod]
public void ListsOfEqualLengthAreComparedByValue()
{
var list1 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 4), 3);
var list2 = new IntegerListThatComparesByLength(new IntegerListPopulatorTestDouble(1, 2, 3), 3);
Assert.IsTrue(list1.CompareTo(list2) > 0);
Assert.IsTrue(list2.CompareTo(list1) < 0);
}
}