如何为泛型提供默认类型?

发布于 2024-07-26 16:22:06 字数 162 浏览 3 评论 0原文

我有一个类,当前有几个采用整数参数的方法。 这些整数映射到应用程序可以执行的操作。 我想让该类变得通用,以便该类的使用者可以提供他们拥有的枚举类型以及其中的所有操作,然后这些方法将采用该枚举类型的参数。 但是,我希望他们能够根本不指定泛型类型,并将其默认返回整数,而当前方式的语法没有变化。 这可能吗?

I have a class that currently has several methods that take integer parameters. These integers map to operations that the application can perform. I'd like to make the class generic so that the consumers of the class can provide an enum type that they have with all the operations in it, then the methods will take parameters of that enum type. However, I want them to be able to not specify a generic type at all, and have it default back to integers with no change in syntax from the current way. Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

記憶穿過時間隧道 2024-08-02 16:22:06

那么...为什么不使用简单继承呢? 就像:

class MyGenericClass<T>
{
}

class MyGenericClass : MyGenericClass<int>
{
}

这样你就可以两种方式写:

var X = new MyGenericClass<string>();
var Y = new MyGenericClass(); // Is now MyGenericClass<int>

So... why not use simple inheritance? Like:

class MyGenericClass<T>
{
}

class MyGenericClass : MyGenericClass<int>
{
}

This way you can write both ways:

var X = new MyGenericClass<string>();
var Y = new MyGenericClass(); // Is now MyGenericClass<int>
如此安好 2024-08-02 16:22:06

你不能在类的定义中做到这一点:

var foo = new MyGenericClass(); // defaults to integer... this doesn't work
var bar = new MyGenericClass<MyEnum>(); // T is a MyEnum

如果真的重视默认类型 int 的隐式性,你将不得不使用静态工厂方法来做到这一点,尽管我没有看到它的价值。

public class MyGenericClass<T>
{
    public static MyGenericClass<T> Create()
    {
        return new MyGenericClass<T>();
    }
    public static MyGenericClass<int> CreateDefault()
    {
        return new MyGenericClass<int>();
    }
}

请参阅下文,了解您如何真正没有从上述内容中受益。

var foo = MyGenericClass<MyEnum>.Create();
var bar1 = MyGenericClass.CreateDefault(); // doesn't work
var bar2 = MyGenericClass<int>.CreateDefault(); // works, but what's the point

如果你想更进一步,你可以创建一个静态工厂类来解决这个问题,但如果你这样做只是为了提供默认类型,那么这是一个更荒谬的解决方案:

public static class MyGenericClassFactory
{
    public static MyGenericClass<T> Create<T>()
    {
        return new MyGenericClass<T>();
    }
    public static MyGenericClass<int> Create()
    {
        return new MyGenericClass<int>();
    }
}

var foo = MyGenericClassFactory.Create(); // now we have an int definition
var bar = MyGenericClassFactory.Create<MyEnum>();

You can't do it in the definition of the class:

var foo = new MyGenericClass(); // defaults to integer... this doesn't work
var bar = new MyGenericClass<MyEnum>(); // T is a MyEnum

If really value the implicitness of the default type being int, you'll have to do it with a static factory method, although I don't see the value of it.

public class MyGenericClass<T>
{
    public static MyGenericClass<T> Create()
    {
        return new MyGenericClass<T>();
    }
    public static MyGenericClass<int> CreateDefault()
    {
        return new MyGenericClass<int>();
    }
}

See below for how you really don't benefit from the above.

var foo = MyGenericClass<MyEnum>.Create();
var bar1 = MyGenericClass.CreateDefault(); // doesn't work
var bar2 = MyGenericClass<int>.CreateDefault(); // works, but what's the point

If you want to take it even farther, you can create a static factory class that will solve this, but that's an even more ridiculous solution if you're doing it for no other reason than to provide a default type:

public static class MyGenericClassFactory
{
    public static MyGenericClass<T> Create<T>()
    {
        return new MyGenericClass<T>();
    }
    public static MyGenericClass<int> Create()
    {
        return new MyGenericClass<int>();
    }
}

var foo = MyGenericClassFactory.Create(); // now we have an int definition
var bar = MyGenericClassFactory.Create<MyEnum>();
_畞蕅 2024-08-02 16:22:06

保留您的原始版本(非通用版本)并创建它的通用版本。

然后从非通用版本调用通用版本。

void Main()
{
    DoSomething(2);
    DoSomething(EnumValue);
}
    
public void DoSomething(int test) {
    DoSomething<int>(test);
}
    
// Define other methods and classes here
public void DoSomething<T>(T test) {
    Console.WriteLine(test);
}

Keep your original version (non-generic version) and create a generic version of it.

Then call the generic version from your non-generic version.

void Main()
{
    DoSomething(2);
    DoSomething(EnumValue);
}
    
public void DoSomething(int test) {
    DoSomething<int>(test);
}
    
// Define other methods and classes here
public void DoSomething<T>(T test) {
    Console.WriteLine(test);
}
鱼窥荷 2024-08-02 16:22:06

大多数时候,编译器可以根据传递的参数类型来推断方法上的参数类型:

public void DoSomething<T>(T test) {
}

可以使用 调用

DoSomething(4);                   // = DoSomething<int>(4);
DoSomething(MyEnum.SomeValue);    // = DoSomething<MyEnum>(MyEnum.SomeValue);

顺便说一句,您也可以拥有泛型方法的非泛型重载。

The compiler can infer the type arguments on methods most of the time based on the type of the arguments passed:

public void DoSomething<T>(T test) {
}

can be called with

DoSomething(4);                   // = DoSomething<int>(4);
DoSomething(MyEnum.SomeValue);    // = DoSomething<MyEnum>(MyEnum.SomeValue);

By the way, you can have non-generic overloads of a generic method too.

你的往事 2024-08-02 16:22:06

我确信您已经离开了这个,但是我正在解决类似的问题,并发现这个解决方案使用了我不熟悉的“使用”上下文。 他们需要将其放在自己的命名空间中,因此它并不完全完美。

namespace mygeneric
{
    public class SecurityContext<T>
    {

    }
}

namespace mytest
{
    using SecurityContext = mygeneric.SecurityContext<int>;
    using mygeneric;

    enum MyContexts
    {
        User,
        Admin
    }
    class MyTest
    {
        SecurityContext myDefaultContext;
        SecurityContext<MyContexts> mySpecialContext;
    }
}

I'm sure you've moved on from this, however I was working through a similar issue and found this solution that uses a context of "using" I was not familiar with. They need to put it in their namespace, so its not completely perfect.

namespace mygeneric
{
    public class SecurityContext<T>
    {

    }
}

namespace mytest
{
    using SecurityContext = mygeneric.SecurityContext<int>;
    using mygeneric;

    enum MyContexts
    {
        User,
        Admin
    }
    class MyTest
    {
        SecurityContext myDefaultContext;
        SecurityContext<MyContexts> mySpecialContext;
    }
}
指尖上的星空 2024-08-02 16:22:06

编译器大多数时候可以根据传递的参数类型推断字段上的类型参数:

import lombok.Data;

@Data
public class MyClass<T> {

    private T myField;
}

可以用作,

MyClass myClass = new MyClass();
String abc = "hello world !";
myClass.setMyField(abc);
System.out.println("test generic class with generic field = " + myGenericClass.getMyField());

并且应该导致,

test generic class with generic field = hello world !

The compiler can infer the type arguments on fields most of the time based on the type of the arguments passed:

import lombok.Data;

@Data
public class MyClass<T> {

    private T myField;
}

can be used as,

MyClass myClass = new MyClass();
String abc = "hello world !";
myClass.setMyField(abc);
System.out.println("test generic class with generic field = " + myGenericClass.getMyField());

and that should result into,

test generic class with generic field = hello world !
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文