c#中是否有类似的类型定义,或者以某种方式获得类似的行为?我在谷歌上搜了一下,但到处都是否定的。目前我的情况类似如下:

class GenericClass<T> 
{
    public event EventHandler<EventData> MyEvent;
    public class EventData : EventArgs { /* snip */ }
    // ... snip
}

现在,当尝试为该事件实现一个处理程序时,这可能很快导致大量输入(为这个可怕的双关语道歉),这并不需要一个火箭科学家来理解。结果是这样的:

GenericClass<int> gcInt = new GenericClass<int>;
gcInt.MyEvent += new EventHandler<GenericClass<int>.EventData>(gcInt_MyEvent);
// ...

private void gcInt_MyEvent(object sender, GenericClass<int>.EventData e)
{
    throw new NotImplementedException();
}

只不过,在我的例子中,我已经使用了复杂类型,而不仅仅是int型。如果能简化一下就好了……

编辑:ie。也许是对EventHandler进行类型定义,而不需要重新定义它来获得类似的行为。


当前回答

你可以使用我创建的一个名为LikeType的开源库和NuGet包,它会给你你正在寻找的GenericClass<int>行为。

代码如下所示:

public class SomeInt : LikeType<int>
{
    public SomeInt(int value) : base(value) { }
}

[TestClass]
public class HashSetExample
{
    [TestMethod]
    public void Contains_WhenInstanceAdded_ReturnsTrueWhenTestedWithDifferentInstanceHavingSameValue()
    {
        var myInt = new SomeInt(42);
        var myIntCopy = new SomeInt(42);
        var otherInt = new SomeInt(4111);

        Assert.IsTrue(myInt == myIntCopy);
        Assert.IsFalse(myInt.Equals(otherInt));

        var mySet = new HashSet<SomeInt>();
        mySet.Add(myInt);

        Assert.IsTrue(mySet.Contains(myIntCopy));
    }
}

其他回答

不,没有typedef的真正对等物。你可以在一个文件中使用“using”指令,例如:

using CustomerList = System.Collections.Generic.List<Customer>;

但这只会影响源文件。在C和c++中,我的经验是typedef通常在广泛包含的.h文件中使用——所以一个typedef可以在整个项目中使用。这种能力在c#中是不存在的,因为c#中没有#include功能来允许你将一个文件中的using指令包含到另一个文件中。

幸运的是,您给出的示例确实有一个固定隐式方法组转换。您可以更改您的事件订阅行:

gcInt.MyEvent += gcInt_MyEvent;

:)

对于非密封类,只需从它们继承:

public class Vector : List<int> { }

但是对于密封类,可以用这样的基类来模拟类型定义行为:

public abstract class Typedef<T, TDerived> where TDerived : Typedef<T, TDerived>, new()
{
    private T _value;

    public static implicit operator T(Typedef<T, TDerived> t)
    {
        return t == null ? default : t._value;
    }

    public static implicit operator Typedef<T, TDerived>(T t)
    {
        return t == null ? default : new TDerived { _value = t };
    }
}

// Usage examples

class CountryCode : Typedef<string, CountryCode> { }
class CurrencyCode : Typedef<string, CurrencyCode> { }
class Quantity : Typedef<int, Quantity> { }

void Main()
{
    var canadaCode = (CountryCode)"CA";
    var canadaCurrency = (CurrencyCode)"CAD";
    CountryCode cc = canadaCurrency;        // Compilation error
    Concole.WriteLine(canadaCode == "CA");  // true
    Concole.WriteLine(canadaCurrency);      // CAD

    var qty = (Quantity)123;
    Concole.WriteLine(qty);                 // 123
}

我会做

using System.Collections.Generic;
global using CustomerList = List<Customer>;

在c# 10中,你可以这样做

global using Bar = Foo

它的工作方式类似于项目中的类型定义。

我还没有对它进行深入测试,所以可能会有一些怪癖。

我用它就像

global using DateTime = DontUseDateTime

其中DontUseDateTime是一个标记为Obsolete的结构体,以强制人们使用NodaTime。

我认为没有类型定义。你只能在GenericClass中定义一个特定的委托类型,而不是泛型委托类型。

public delegate GenericHandler EventHandler<EventData>

这会使它更短。但是下面的建议怎么样:

使用Visual Studio。这样,当你打字的时候

gcInt.MyEvent += 

它已经从智能感知中提供了完整的事件处理程序签名。按TAB键,它就在那里。接受生成的处理程序名称或更改它,然后再次按TAB键自动生成处理程序存根。