118 строки
3.0 KiB
C#
118 строки
3.0 KiB
C#
// Copyright 2016 Xamarin Inc. All rights reserved.
|
|
|
|
using System;
|
|
#if XAMCORE_2_0
|
|
using Foundation;
|
|
#else
|
|
using MonoTouch.Foundation;
|
|
#endif
|
|
using NUnit.Framework;
|
|
|
|
namespace Linker.Sealer {
|
|
|
|
[Preserve (AllMembers = true)]
|
|
public class Unsealable {
|
|
|
|
public virtual bool A () { return true; }
|
|
public virtual bool B () { return false; }
|
|
}
|
|
|
|
[Preserve (AllMembers = true)]
|
|
public class Sealable : Unsealable {
|
|
public override bool B () { return true; }
|
|
public virtual bool C () { return false; }
|
|
}
|
|
|
|
interface Interface {
|
|
bool A ();
|
|
}
|
|
|
|
[Preserve (AllMembers = true)]
|
|
public class Base {
|
|
public bool A () { return true; }
|
|
}
|
|
|
|
[Preserve (AllMembers = true)]
|
|
public class Subclass : Base, Interface {
|
|
}
|
|
|
|
[TestFixture]
|
|
[Preserve (AllMembers = true)]
|
|
public class SealerTest {
|
|
|
|
[Test]
|
|
public void Sealed ()
|
|
{
|
|
// this can not be optimized into a sealed type
|
|
Assert.False (typeof (Unsealable).IsSealed, "Unsealed");
|
|
#if DEBUG
|
|
// this is not a sealed type (in the source)
|
|
Assert.False (typeof (Sealable).IsSealed, "Sealable");
|
|
Assert.False (typeof (Base).IsSealed, "Base");
|
|
Assert.False (typeof (Subclass).IsSealed, "Subclass");
|
|
Assert.False (typeof (Interface).IsSealed, "Interface");
|
|
#else
|
|
// Sealable can be optimized / sealed as nothing else is (or can) subclass it
|
|
Assert.True (typeof (Sealable).IsSealed, "Sealable");
|
|
// Base is subclassed so it can't be sealed
|
|
Assert.False (typeof (Base).IsSealed, "Base");
|
|
// Subclass is not subclassed anymore and can be sealed
|
|
Assert.True (typeof (Subclass).IsSealed, "Subclass");
|
|
// interface can not be sealed
|
|
Assert.False (typeof (Interface).IsSealed, "Interface");
|
|
#endif
|
|
}
|
|
|
|
[Test]
|
|
public void Final ()
|
|
{
|
|
var t = typeof (Sealable);
|
|
var a = t.GetMethod ("A");
|
|
var b = t.GetMethod ("B");
|
|
var c = t.GetMethod ("C");
|
|
#if DEBUG
|
|
// this is not a sealed (C#) method (in the source)
|
|
Assert.False (a.IsFinal, "A");
|
|
Assert.False (b.IsFinal, "B");
|
|
Assert.False (c.IsFinal, "C");
|
|
#else
|
|
// but it can be optimized / sealed as nothing else is (or can) overrides it
|
|
Assert.True (a.IsFinal, "A");
|
|
Assert.True (b.IsFinal, "B");
|
|
Assert.True (c.IsFinal, "C");
|
|
#endif
|
|
}
|
|
|
|
[Test]
|
|
public void Virtual ()
|
|
{
|
|
var t = typeof (Sealable);
|
|
var a = t.GetMethod ("A");
|
|
var b = t.GetMethod ("B");
|
|
var c = t.GetMethod ("C");
|
|
#if DEBUG
|
|
// both methods are virtual (both in C# and IL)
|
|
Assert.True (a.IsVirtual, "A");
|
|
Assert.True (b.IsVirtual, "B");
|
|
Assert.True (c.IsVirtual, "C");
|
|
#else
|
|
// calling A needs dispatch to base type Unsealable
|
|
Assert.True (a.IsVirtual, "A");
|
|
// B is an override and must remain virtual
|
|
Assert.True (b.IsVirtual, "B");
|
|
// C has no special requirement and can be de-virtualized
|
|
Assert.False (c.IsVirtual, "C");
|
|
#endif
|
|
}
|
|
|
|
[Test]
|
|
public void Interface ()
|
|
{
|
|
var t = typeof (Subclass);
|
|
var a = t.GetMethod ("A");
|
|
// A cannot be de-virtualized since Concrete must satisfy Interface thru Base
|
|
Assert.True (a.IsVirtual, "A");
|
|
}
|
|
}
|
|
}
|